847 lines
22 KiB
Vue
Raw Normal View History

2025-09-01 16:05:31 +08:00
<template>
<view class="order-detail-container">
<!-- 基础信息区域 -->
<view class="info-section">
<uni-row class="info-grid">
<uni-col class="flex-row">
<view class="label">生产单位: </view>
<uni-data-select
2026-02-12 14:41:15 +08:00
v-model="form.companyId"
:localdata="companyOptions"
text-field="text"
value-field="value"
:disabled="true"
/>
2025-09-01 16:05:31 +08:00
</uni-col>
</uni-row>
<uni-row class="info-grid">
<uni-col :span="12">
2026-02-12 14:41:15 +08:00
<view v-if="creditperiValue == 0" class="label">剩余金额:现款</view>
<view v-else class="label">剩余金额:{{ remainingMoney }}</view>
2025-09-01 16:05:31 +08:00
</uni-col>
<uni-col :span="12">
<view class="label">订单金额:{{ orderAmount }}</view>
</uni-col>
</uni-row>
<uni-row class="info-grid">
<uni-col :span="24" style="display: flex;">
<view class="label">已选补差:</view>
2026-02-12 14:41:15 +08:00
<view class="">
<view style="color: red;font-size: 14px;" v-if="buchaGoodsList.length && selectedBuChaItems.length==0">
&nbsp;&nbsp;提示:当前有补差数据可选择
</view>
<view v-else class="" v-for="(item,index) in selectedBuChaItems" :key="index">
商品{{item.goodsname}},金额{{item.piaokou}}
</view>
</view>
2025-09-01 16:05:31 +08:00
</uni-col>
</uni-row>
2026-02-12 14:41:15 +08:00
<button type="primary"
@click="showBuchaList"
v-show="buchaGoodsList.length > 0 && !isShowingBuchaList"
size="default"
>
选择补差
</button>
<button type="primary" @click="showGoodsList" v-show="isShowingBuchaList">
返回商品列表
</button>
2025-09-01 16:05:31 +08:00
</view>
2026-02-12 14:41:15 +08:00
<!-- 补差列表 -->
<view v-if="isShowingBuchaList">
<view class="goods-section">
<view class="section-title">
<view class="">补差商品信息</view>
<view class="select-all">
<checkbox
:checked="allSelected"
@click="toggleSelectAll"
></checkbox>
2025-09-01 16:05:31 +08:00
</view>
</view>
2026-02-12 14:41:15 +08:00
<view v-if="buchaGoodsList.length === 0" class="no-data">
暂无补差数据
</view>
<view v-else class="goods-double-column">
<checkbox-group @change="checkboxChange">
<view
v-for="(goods, index) in buchaGoodsList"
:key="goods.piaokouid"
class="goods-item"
>
<view class="goods-header">
<text class="serial-number">{{ index + 1 }}</text>
<text class="goods-name">{{ goods.goodsname }}</text>
<checkbox :checked="selectedBuChaItems.some(item => item.piaokouid === goods.piaokouid)"
:value="String(goods.piaokouid)"></checkbox>
</view>
<view class="goods-content">
<uni-row class="info-row">
<uni-col :span="12" class="info-pair">
<view class="label">申请日期:{{ goods.applydate }}</view>
</uni-col>
<uni-col :span="12" class="info-pair">
<view class="label">补差类型:{{ goods.piaokoutype }}</view>
</uni-col>
</uni-row>
<uni-row class="info-row">
<uni-col :span="12" class="info-pair">
<view class="label">商品简称:{{ goods.shortname }}</view>
</uni-col>
<uni-col :span="12" class="info-pair">
<view class="label">可补差金额:{{ goods.piaokou }}</view>
</uni-col>
</uni-row>
</view>
</view>
</checkbox-group>
</view>
</view>
<!-- 补差操作按钮 -->
<view class="action-buttons">
<button @click="goAdd" class="btn btn-secondary">添加补差</button>
<button @click="showGoodsList" class="btn btn-primary">取消</button>
2025-09-01 16:05:31 +08:00
</view>
</view>
2026-02-12 14:41:15 +08:00
<!-- 商品信息区域 -->
<view v-if="!isShowingBuchaList">
<MBLoading v-if="loading"/>
<view v-else>
<view class="goods-section">
<view class="section-title">商品信息</view>
<view v-if="goodsList.length === 0" class="no-data">
暂无商品数据
2025-09-01 16:05:31 +08:00
</view>
2026-02-12 14:41:15 +08:00
<view v-else class="goods-double-column">
<view
v-for="(goods, index) in goodsList"
:key="goods.goodsid"
class="goods-item"
>
<view class="goods-header">
<text class="serial-number">{{ index + 1 }}</text>
<text class="goods-name">{{ goods.goodsname }}</text>
</view>
<view class="goods-content">
<uni-row class="info-row">
<uni-col :span="12" class="info-pair">
<view class="label">件装数:{{ goods.packingnum }}</view>
</uni-col>
<uni-col :span="12" class="info-pair">
<view class="label">供应参考价:{{ goods.invoiceprice }}</view>
</uni-col>
</uni-row>
<uni-row class="info-row">
<uni-col :span="12" class="info-pair">
<view class="label">前三月平均数:{{ goods.threeMonths }}</view>
</uni-col>
<uni-col :span="12" class="info-pair">
<view class="label">使用票扣:{{ goods.piaokou }}</view>
</uni-col>
</uni-row>
<uni-row class="info-row">
<uni-col :span="12" class="info-pair">
<view class="label">小计:{{ goods.allmoney }}</view>
</uni-col>
<uni-col :span="12" class="info-pair">
<view class="label">税率:{{ goods.taxrate }}</view>
</uni-col>
</uni-row>
<uni-row class="info-row">
<uni-col :span="12" class="info-pair flex-row" >
<view class="label">采购数量:</view>
<input
class="uni-input custom-input"
v-model="goods.goodsnum"
placeholder="请输入采购数量"
@blur="e => handleInput(e,index)"/>
</uni-col>
</uni-row>
</view>
</view>
2025-09-01 16:05:31 +08:00
</view>
</view>
2026-02-12 14:41:15 +08:00
<!-- 商品列表操作按钮 -->
<view class="action-buttons ">
<button @click="goSave" class="btn btn-secondary" :loading="btnloading" :disabled="btnloading">保存</button>
<button @click="goSubmit" class="btn btn-primary":loading="btnloading" :disabled="btnloading">确认提交</button>
</view>
2025-09-01 16:05:31 +08:00
</view>
</view>
</view>
</template>
<script setup>
2026-02-12 14:41:15 +08:00
import { onLoad } from '@dcloudio/uni-app'
import { onMounted, ref, nextTick } from 'vue'
import { productListWithUserId, addsalemain, getsalemaincheckAmount, listsaleBusGoodsList, salemainpiAoKouList } from '../../../../api/orderManager/index.js'
import { useUserStore } from '@/store'
import MBLoading from "@/components/MB/MBLoading.vue";
const userStore = useUserStore()
const userID = ref(userStore.id)
const loading = ref(true)
const btnloading = ref(false)
// 状态控制
const isShowingBuchaList = ref(false) // 是否显示补差列表
// 数据
const selectedBuChaItems = ref([]) // 已选补差具体项
const buchaGoodsList = ref([]) // 补差商品列表
const goodsList = ref([]) // 商品列表
const form = ref({ companyId: null })
const remainingMoney = ref(0) // 剩余金额
const orderAmount = ref(0.00) // 订单金额
const creditperiValue = ref() // 信用期
// 补差选择相关
const allSelected = ref(false) // 是否全选
const tempSelectedItems = ref([]) // 临时选中的补差项
// 生产单位选项
2025-09-01 16:05:31 +08:00
const companyOptions = ref([])
2026-02-12 14:41:15 +08:00
const isInitializing = ref(false)
// 页面加载时获取参数
onLoad((options) => {
// 方式2获取完整参数如果通过data传递
if (options.data) {
try {
const params = JSON.parse(decodeURIComponent(options.data))
form.value = params
getEdu()
// 设置其他字段
} catch (e) {
console.error('解析参数失败:', e)
}
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
// console.log('接收到的订单ID:', )
})
onMounted(async () => {
isInitializing.value = true
try {
await getDeptLists()
if (companyOptions.value.length > 0) {
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
} catch (error) {
console.error('初始化失败:', error)
} finally {
isInitializing.value = false
}
})
/** 查询部门列表 */
async function getDeptLists() {
try {
const res = await productListWithUserId()
const sortedData = [...res.data].sort((a, b) => {
const order = [4, 1, 2, 3]
return order.indexOf(a.companyId) - order.indexOf(b.companyId)
})
companyOptions.value = sortedData.map(item => ({
value: item.companyId,
text: item.companyName
}))
if (companyOptions.value.length > 0) {
// form.value.companyId = companyOptions.value[0].value
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
return companyOptions.value
} catch (error) {
console.error('获取部门列表失败:', error)
throw error
}
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
// 获取补差列表数据
function getsalemainpiAoKouList() {
const body = { companyId: form.value.companyId }
salemainpiAoKouList(body).then(res => {
buchaGoodsList.value = res.data || []
})
}
// 获取商品列表
function GetlistsaleBusGoodsList() {
loading.value = true
const KeSaleGoodsParams = {
companyId: form.value.companyId,
userid: form.value.userid,
deleteflag: 0,
saleId:form.value.saleid
}
const KeSaleGoodsQuery = { pageNum: 1, pageSize: 999 }
listsaleBusGoodsList(KeSaleGoodsParams, KeSaleGoodsQuery).then(res => {
goodsList.value = res.data || []
loading.value = false
// 计算所有小计之和(确保两位小数)
const totalXiaoji = res.data.reduce((sum, item) => {
const xiaoji = Math.round(item.invoiceprice * Number(item.goodsnum) * 100) / 100;
return sum + xiaoji;
}, 0);
// // 格式化总金额,确保两位小数(数字类型)
const formattedTotal = Number(totalXiaoji.toFixed(2));
orderAmount.value = formattedTotal;
})
}
2025-09-01 16:05:31 +08:00
/** 更改生产单位时,查询额度 */
function getEdu() {
2026-02-12 14:41:15 +08:00
console.log('生产单位ID:', form.value.companyId)
// 确保显示商品列表
isShowingBuchaList.value = false
// 清空已选补差数据
selectedBuChaItems.value = []
tempSelectedItems.value = []
allSelected.value = false
const AmountqueryParams = {
companyId: form.value.companyId,
saleId: 0,
}
getsalemaincheckAmount(AmountqueryParams).then(res => {
if (res.data) {
creditperiValue.value = res.data.creditperiod
remainingMoney.value = res.data.amounts
} else {
remainingMoney.value = 0
2025-09-01 16:05:31 +08:00
}
GetlistsaleBusGoodsList()
getsalemainpiAoKouList()
2026-02-12 14:41:15 +08:00
})
}
2025-09-01 16:05:31 +08:00
2026-02-12 14:41:15 +08:00
/** 显示补差列表 */
function showBuchaList() {
isShowingBuchaList.value = true
// 将已选补差同步到临时选中项
tempSelectedItems.value = [...selectedBuChaItems.value]
updateAllSelectedState()
window.scrollTo({ top: 0, behavior: 'smooth' })
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
/** 显示商品列表 */
function showGoodsList() {
isShowingBuchaList.value = false
window.scrollTo({ top: 0, behavior: 'smooth' })
}
/** 更新全选状态 */
function updateAllSelectedState() {
if (buchaGoodsList.value.length === 0) {
allSelected.value = false
return
}
const allIds = buchaGoodsList.value.map(item => item.piaokouid)
const selectedIds = tempSelectedItems.value.map(item => item.piaokouid)
allSelected.value = allIds.length > 0 &&
allIds.every(id => selectedIds.includes(id))
}
/** 补差选择变化 */
const checkboxChange = (value) => {
console.log('checkboxChange触发value:', value)
const idList = value.detail.value
// 清空临时选中项
tempSelectedItems.value = []
// 根据选中的ID列表重新构建选中项
if (idList.length > 0) {
buchaGoodsList.value.forEach(item => {
if (idList.includes(String(item.piaokouid))) {
tempSelectedItems.value.push({
piaokouid: item.piaokouid,
goodsid: item.goodsid,
goodsname: item.goodsname,
piaokou: item.piaokou,
applydate: item.applydate,
piaokoutype: item.piaokoutype,
shortname: item.shortname
})
}
})
}
// 更新全选状态
updateAllSelectedState()
console.log('当前选中的补差项:', tempSelectedItems.value)
}
/** 全选/全不选 */
const toggleSelectAll = () => {
if (!allSelected.value) {
// 全选
tempSelectedItems.value = [...buchaGoodsList.value]
allSelected.value = true
} else {
// 全不选
tempSelectedItems.value = []
allSelected.value = false
}
}
/** 添加补差 */
const goAdd = () => {
console.log('点击添加补差,当前选中的补差数据:', tempSelectedItems.value)
if (tempSelectedItems.value.length === 0) {
uni.showToast({
title: '请选择补差数据!',
icon: 'none',
duration: 2000
})
return
}
// 调用选择补差函数
ChooseBtn(tempSelectedItems.value)
uni.showToast({
title: '添加成功!',
icon: 'success',
duration: 2000
})
showGoodsList()
}
/** 选择补差按钮逻辑 */
const ChooseBtn = (data) => {
console.log('ChooseBtn被调用传入数据:', data)
// 隐藏补差列表
isShowingBuchaList.value = false
if (!Array.isArray(data)) {
console.error('补差数据不是数组:', data)
data = []
}
// 保存当前选中的具体补差项
selectedBuChaItems.value = [...data]
// 1. 先清空所有商品的补差金额
goodsList.value = goodsList.value.map(item => ({
...item,
piaokou: 0
}))
// 2. 按 goodsid 汇总补差金额
const piaokouMap = data.reduce((acc, item) => {
const goodsid = item.goodsid
acc[goodsid] = (acc[goodsid] || 0) + (Number(item.piaokou) || 0)
return acc
}, {})
console.log('补差金额汇总结果:', piaokouMap)
// 3. 更新对应商品的补差金额
goodsList.value = goodsList.value.map(item => {
if (piaokouMap.hasOwnProperty(item.goodsid)) {
return {
...item,
piaokou: Number(piaokouMap[item.goodsid]) // 保持为数字类型
}
}
return item
})
console.log('更新后的商品列表:', goodsList.value)
}
/** 计算小计 */
2025-09-01 16:05:31 +08:00
const handleInput = (e, index) => {
2026-02-12 14:41:15 +08:00
const value = e.detail ? e.detail.value : e.target.value
2025-09-01 16:05:31 +08:00
const num = Number(value)
2026-02-12 14:41:15 +08:00
if (isNaN(num)) {
goodsList.value[index].goodsnum = 0
goodsList.value[index].allmoney = 0
return
}
2025-09-01 16:05:31 +08:00
// 更新采购数量
2026-02-12 14:41:15 +08:00
goodsList.value[index].goodsnum = num
2025-09-01 16:05:31 +08:00
// 重新计算小计 = 采购数量 × 供应参考价
2026-02-12 14:41:15 +08:00
const invoiceprice = Number(goodsList.value[index].invoiceprice) || 0
goodsList.value[index].allmoney = Math.ceil(num * invoiceprice * 100) / 100
// 计算订单总金额
orderAmount.value = goodsList.value.reduce((sum, item) => {
const num = Number(item.goodsnum) || 0
const price = Number(item.invoiceprice) || 0
return sum + num * price
}, 0)
orderAmount.value = Math.ceil(orderAmount.value * 100) / 100
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
/** 验证票扣金额 - 简化版 */
2025-09-01 16:05:31 +08:00
const validatePiaokou = () => {
2026-02-12 14:41:15 +08:00
// 找出所有商品中票扣大于小计的情况
const invalidItems = goodsList.value.filter(item => {
const piaokou = Number(item.piaokou || 0)
const allmoney = Number(item.allmoney || 0)
// 只需判断票扣是否大于小计
return piaokou > allmoney
})
2025-09-01 16:05:31 +08:00
if (invalidItems.length > 0) {
// 构建错误提示信息
const errorMessage = `以下商品的票扣金额大于小计金额:\n` +
invalidItems.map(item =>
2026-02-12 14:41:15 +08:00
`- ${item.goodsname} (票扣: ${item.piaokou}, 小计: ${item.allmoney})`
).join('\n')
2025-09-01 16:05:31 +08:00
uni.showToast({
title: errorMessage,
icon: 'none',
duration: 3000
2026-02-12 14:41:15 +08:00
})
return false
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
//增加订单金额不能大于剩余金额判断
if(orderAmount.value > remainingMoney.value){
uni.showToast({
title: '订单金额不能大于剩余金额!',
icon: 'none',
duration: 2000
})
return false
}
return true
}
/** 保存 */
2025-09-01 16:05:31 +08:00
const goSave = () => {
2026-02-12 14:41:15 +08:00
const filteredData = goodsList.value.filter(item =>
item.goodsnum !== null &&
item.goodsnum !== '' &&
Number(item.goodsnum) !== 0 &&
!isNaN(Number(item.goodsnum))
)
2025-09-01 16:05:31 +08:00
2026-02-12 14:41:15 +08:00
if (filteredData.length === 0) {
uni.showToast({
title: '请至少选择一个商品并输入采购数量!',
icon: 'none',
duration: 2000
})
return
}
form.value.saledetailList = filteredData.map(item => ({
...item,
price: item.invoiceprice,
xiaoji: item.allmoney
}))
// 添加验证
if (!validatePiaokou()) {
return // 验证不通过,停止执行
}
btnloading.value = true
form.value.state = 0 // 0为保存可修改编辑1的时候为提交
addsalemain(form.value).then(res => {
uni.showToast({
title: '保存成功!',
icon: 'success',
duration: 2000
})
btnloading.value = false
uni.navigateTo({
url: '/pages/work/OrderManager/index'
})
}).catch(err => {
console.error('保存失败:', err)
uni.showToast({
title: '保存失败!',
icon: 'error',
duration: 2000
})
btnloading.value = false
})
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
/** 提交 */
2025-09-01 16:05:31 +08:00
const goSubmit = () => {
2026-02-12 14:41:15 +08:00
const filteredData = goodsList.value.filter(item =>
item.goodsnum !== null &&
item.goodsnum !== '' &&
Number(item.goodsnum) !== 0 &&
!isNaN(Number(item.goodsnum))
)
if (filteredData.length === 0) {
uni.showToast({
title: '请至少选择一个商品并输入采购数量!',
icon: 'none',
duration: 2000
})
return
}
form.value.saledetailList = filteredData.map(item => ({
...item,
price: item.invoiceprice,
xiaoji: item.allmoney
}))
// 添加验证
if (!validatePiaokou()) {
return // 验证不通过,停止执行
}
btnloading.value = true
form.value.state = 1 // 1为提交
addsalemain(form.value).then(res => {
uni.showToast({
title: '提交成功!',
icon: 'success',
duration: 2000
})
btnloading.value = false
uni.navigateTo({
url: '/pages/work/OrderManager/index'
})
}).catch(err => {
console.error('提交失败:', err)
uni.showToast({
title: '提交失败!',
icon: 'error',
duration: 2000
})
btnloading.value = false
})
2025-09-01 16:05:31 +08:00
}
</script>
<style lang="scss" scoped>
2026-02-12 14:41:15 +08:00
.select-all {
margin-left: auto;
}
2025-09-01 16:05:31 +08:00
.custom-input {
border: 1px solid #ccc;
border-radius: 4px;
padding: 5px;
height: 25px;
2026-02-12 14:41:15 +08:00
width: 80px;
2025-09-01 16:05:31 +08:00
}
2026-02-12 14:41:15 +08:00
2025-09-01 16:05:31 +08:00
.order-detail-container {
padding: 16px;
background-color: #f5f5f5;
min-height: 100vh;
}
2026-02-12 14:41:15 +08:00
2025-09-01 16:05:31 +08:00
.flex-row {
display: flex;
2026-02-12 14:41:15 +08:00
align-items: center;
gap: 10px;
2025-09-01 16:05:31 +08:00
}
.info-section {
background: #fff;
border-radius: 12px;
padding: 16px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.info-grid {
margin-bottom: 20rpx;
margin-top: 20rpx;
}
.label {
font-size: 14px;
color: #666;
margin-bottom: 4px;
font-weight: 500;
}
.amount {
color: #f56c6c;
font-weight: 600;
}
/* 商品信息区域 */
.goods-section {
background: #fff;
border-radius: 12px;
padding: 16px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.section-title {
font-size: 16px;
color: #333;
margin: 0 0 16px 0;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
font-weight: 600;
display: flex;
align-items: center;
}
.no-data {
text-align: center;
color: #999;
padding: 40px 0;
font-size: 14px;
}
/* 商品双栏布局 */
.goods-double-column {
display: flex;
flex-direction: column;
gap: 12px;
}
.goods-item {
border: 1px solid #eee;
border-radius: 12px;
overflow: hidden;
background: #fafafa;
}
.goods-header {
background: #409eff;
color: white;
2026-02-10 16:39:04 +08:00
padding: 5px 8px;
2025-09-01 16:05:31 +08:00
display: flex;
align-items: center;
gap: 12px;
}
.serial-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
font-size: 12px;
font-weight: 600;
}
.goods-name {
font-size: 15px;
font-weight: 600;
flex: 1;
}
/* 商品内容区域 */
.goods-content {
padding: 12px 16px;
}
.info-row {
display: flex;
margin-bottom: 8px;
}
.info-pair {
flex: 1;
padding: 0 8px;
}
.info-pair .label {
font-size: 14px;
color: #666;
margin-bottom: 2px;
}
.info-pair .value {
font-size: 14px;
color: #333;
font-weight: 500;
text-align: right;
}
/* 操作按钮 */
.action-buttons {
display: flex;
justify-content: center;
gap: 12px;
2026-02-12 14:41:15 +08:00
padding: 16px;
2025-09-01 16:05:31 +08:00
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.btn {
2026-02-12 14:41:15 +08:00
padding: 2px 0;
2025-09-01 16:05:31 +08:00
border: none;
2026-02-12 14:41:15 +08:00
// border-radius: 8px;
font-size: 14px;
2025-09-01 16:05:31 +08:00
font-weight: 500;
cursor: pointer;
min-width: 80px;
text-align: center;
flex: 1;
}
.btn-primary {
background: #409eff;
color: white;
2026-02-12 14:41:15 +08:00
font-size: 14px;
2025-09-01 16:05:31 +08:00
}
.btn-secondary {
background: #67c23a;
color: white;
2026-02-12 14:41:15 +08:00
font-size: 14px;
2025-09-01 16:05:31 +08:00
}
/* 响应式设计 */
@media (max-width: 768px) {
.order-detail-container {
padding: 12px;
}
.action-buttons {
flex-direction: column;
}
.btn {
width: 100%;
margin-bottom: 8px;
}
.btn:last-child {
margin-bottom: 0;
}
}
2026-02-12 14:41:15 +08:00
uni-button{
padding: 2px 0;
font-size: 14px;
2025-09-01 16:05:31 +08:00
}
</style>