<template>
|
<view class="account-detail">
|
<!-- 使用通用页面头部组件 -->
|
<PageHeader title="新增开票登记" @back="goBack" />
|
|
<!-- 表单内容 -->
|
<up-form @submit="submitForm" ref="formRef" label-width="130" :rules="rules" :model="form">
|
<!-- 基本信息 -->
|
<view class="form-section">
|
<up-form-item label="销售合同号" prop="salesContractNo">
|
<up-input v-model="form.salesContractNo" placeholder="自动填充" disabled />
|
</up-form-item>
|
<up-form-item label="客户名称" prop="customerName">
|
<up-input v-model="form.customerName" placeholder="自动填充" disabled />
|
</up-form-item>
|
<up-form-item label="业务员" prop="salesman">
|
<up-input v-model="form.salesman" placeholder="自动填充" disabled />
|
</up-form-item>
|
<up-form-item label="项目名称" prop="projectName">
|
<up-input v-model="form.projectName" placeholder="自动填充" disabled />
|
</up-form-item>
|
<up-form-item label="录入人" prop="createUer">
|
<up-input v-model="form.createUer" placeholder="请输入录入人" disabled />
|
</up-form-item>
|
<up-form-item
|
label="录入日期"
|
prop="createTime"
|
@click="showCreateTimePicker = true"
|
>
|
<up-input
|
v-model="form.createTime"
|
placeholder="请选择录入日期"
|
readonly
|
@click="showCreateTimePicker = true"
|
/>
|
<template #right>
|
<up-icon name="arrow-right" @click="showCreateTimePicker = true"></up-icon>
|
</template>
|
</up-form-item>
|
<up-form-item label="发票号码" prop="invoiceNo" required>
|
<up-input v-model="form.invoiceNo" placeholder="请输入发票号码" />
|
</up-form-item>
|
<up-form-item
|
label="开票日期"
|
prop="issueDate"
|
required
|
@click="showIssueDatePicker = true"
|
>
|
<up-input
|
v-model="form.issueDate"
|
placeholder="请选择开票日期"
|
readonly
|
@click="showIssueDatePicker = true"
|
/>
|
<template #right>
|
<up-icon name="arrow-right" @click="showIssueDatePicker = true"></up-icon>
|
</template>
|
</up-form-item>
|
</view>
|
|
<!-- 产品信息 -->
|
<view class="product-section">
|
<view class="section-header">
|
<view>
|
<text class="section-title">产品信息</text>
|
</view>
|
</view>
|
|
<view v-if="productData.length === 0" class="empty-state">
|
<view class="empty-text">暂无产品数据</view>
|
</view>
|
|
<view v-else class="product-list">
|
<view
|
v-for="(item, index) in productData"
|
:key="index"
|
class="product-card"
|
>
|
<!-- 产品头部 -->
|
<view class="product-header">
|
<view class="product-title">
|
<view class="document-icon">
|
<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
|
</view>
|
<text class="product-productCategory">产品 {{ index + 1 }}</text>
|
</view>
|
</view>
|
|
<!-- 产品信息表单 -->
|
<view class="product-form">
|
<up-form-item label="产品大类" prop="productCategory">
|
<up-input v-model="item.productCategory" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="规格型号" prop="specificationModel">
|
<up-input v-model="item.specificationModel" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="单位" prop="unit">
|
<up-input v-model="item.unit" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="数量" prop="quantity">
|
<up-input v-model="item.quantity" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="税率(%)" prop="taxRate">
|
<up-input v-model="item.taxRate" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="含税单价(元)" prop="taxInclusiveUnitPrice">
|
<up-input v-model="item.taxInclusiveUnitPrice" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="含税总价(元)" prop="taxInclusiveTotalPrice">
|
<up-input v-model="item.taxInclusiveTotalPrice" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="不含税总价(元)" prop="taxExclusiveTotalPrice">
|
<up-input v-model="item.taxExclusiveTotalPrice" placeholder="" disabled />
|
</up-form-item>
|
|
<!-- 本次开票信息 -->
|
<up-form-item label="本次开票数" prop="currentInvoiceNum">
|
<up-input
|
v-model="item.currentInvoiceNum"
|
type="number"
|
placeholder="请输入开票数量"
|
@blur="invoiceNumBlur(item)"
|
/>
|
</up-form-item>
|
<up-form-item label="本次开票金额(元)" prop="currentInvoiceAmount">
|
<up-input
|
v-model="item.currentInvoiceAmount"
|
type="number"
|
placeholder="请输入开票金额"
|
@blur="invoiceAmountBlur(item)"
|
/>
|
</up-form-item>
|
|
<!-- 未开票信息 -->
|
<up-form-item label="未开票数" prop="noInvoiceNum">
|
<up-input v-model="item.noInvoiceNum" placeholder="" disabled />
|
</up-form-item>
|
<up-form-item label="未开票金额(元)" prop="noInvoiceAmount">
|
<up-input v-model="item.noInvoiceAmount" placeholder="" disabled />
|
</up-form-item>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 使用公共底部按钮组件 -->
|
<FooterButtons
|
show
|
cancelText="取消"
|
confirmText="保存"
|
@cancel="goBack"
|
@confirm="submitForm"
|
/>
|
</up-form>
|
|
<!-- 日期选择器 -->
|
<up-popup :show="showIssueDatePicker" mode="bottom" @close="showIssueDatePicker = false">
|
<up-datetime-picker
|
:show="true"
|
v-model="pickerIssueDateValue"
|
@confirm="onIssueDateConfirm"
|
@cancel="showIssueDatePicker = false"
|
mode="date"
|
/>
|
</up-popup>
|
|
<up-popup :show="showCreateTimePicker" mode="bottom" @close="showCreateTimePicker = false">
|
<up-datetime-picker
|
:show="true"
|
v-model="pickerCreateTimeValue"
|
@confirm="onCreateTimeConfirm"
|
@cancel="showCreateTimePicker = false"
|
mode="date"
|
/>
|
</up-popup>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, onMounted } from 'vue'
|
// 替换 toast 方法
|
const showToast = (message) => {
|
uni.showToast({
|
title: message,
|
icon: 'none'
|
})
|
}
|
|
const showLoadingToast = (message) => {
|
uni.showLoading({
|
title: message || '加载中...'
|
})
|
}
|
|
const closeToast = () => {
|
uni.hideLoading()
|
}
|
import { invoiceRegistrationSave } from '@/api/salesManagement/invoiceRegistration'
|
import useUserStore from '@/store/modules/user'
|
import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger";
|
import FooterButtons from '@/components/FooterButtons.vue';
|
import { formatDateToYMD } from '@/utils/ruoyi'
|
|
const userStore = useUserStore()
|
const editData = ref(null);
|
|
// 表单引用
|
const formRef = ref()
|
|
// 表单数据
|
let form = ref({
|
salesContractNo: '',
|
customerName: '',
|
salesman: '',
|
projectName: '',
|
createUer: '',
|
issueDate: '',
|
createTime: '',
|
invoiceNo: ''
|
})
|
|
// 表单校验规则
|
const rules = {
|
invoiceNo: [
|
{ required: true, message: '请输入发票号码', trigger: 'blur' }
|
],
|
issueDate: [
|
{ required: true, message: '请选择开票日期', trigger: 'blur' }
|
]
|
};
|
|
// 产品数据
|
const productData = ref([])
|
|
// 日期选择器状态
|
const showIssueDatePicker = ref(false)
|
const showCreateTimePicker = ref(false)
|
const pickerIssueDateValue = ref(Date.now())
|
const pickerCreateTimeValue = ref(Date.now())
|
|
// 提交状态
|
const submitting = ref(false)
|
|
// 返回上一页
|
const goBack = () => {
|
// 清理本地存储的数据
|
uni.removeStorageSync('editData');
|
uni.navigateBack()
|
}
|
|
// 格式化数字
|
const formatNumber = (value, precision = 2) => {
|
if (!value && value !== 0) return '0.00'
|
return Number(value).toFixed(precision)
|
}
|
|
// 开票数量变化处理
|
const invoiceNumBlur = (row) => {
|
if (!row.currentInvoiceNum) {
|
row.currentInvoiceNum = 0;
|
}
|
if (row.currentInvoiceNum > row.tempNoInvoiceNum) {
|
showToast('本次开票数不得大于未开票数')
|
row.currentInvoiceNum = 0;
|
}
|
// 计算本次开票金额
|
row.currentInvoiceAmount = (
|
row.currentInvoiceNum * row.taxInclusiveUnitPrice
|
).toFixed(2);
|
// 计算未开票数
|
row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
|
2
|
);
|
// 计算未开票金额
|
row.noInvoiceAmount = (
|
row.tempnoInvoiceAmount - row.currentInvoiceAmount
|
).toFixed(2);
|
}
|
|
// 开票金额变化处理
|
const invoiceAmountBlur = (row) => {
|
if (!row.currentInvoiceAmount) {
|
row.currentInvoiceAmount = 0;
|
}
|
// 计算是否超过开票总金额
|
if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) {
|
showToast('本次开票金额不得大于未开票金额')
|
row.currentInvoiceAmount = 0;
|
}
|
// 计算本次开票数
|
row.currentInvoiceNum = (
|
row.currentInvoiceAmount / row.taxInclusiveUnitPrice
|
).toFixed(2);
|
// 计算未开票数
|
row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
|
2
|
);
|
// 计算未开票金额
|
row.noInvoiceAmount = (
|
row.tempnoInvoiceAmount - row.currentInvoiceAmount
|
).toFixed(2);
|
}
|
|
// 更新未开票数据
|
const updateNoInvoiceData = (row) => {
|
const totalQuantity = parseFloat(row.quantity) || 0
|
const currentInvoiceNum = parseFloat(row.currentInvoiceNum) || 0
|
const totalAmount = parseFloat(row.taxInclusiveTotalPrice) || 0
|
const currentInvoiceAmount = parseFloat(row.currentInvoiceAmount) || 0
|
|
row.noInvoiceNum = Math.max(0, totalQuantity - currentInvoiceNum).toFixed(2)
|
row.noInvoiceAmount = Math.max(0, totalAmount - currentInvoiceAmount).toFixed(2)
|
}
|
|
// 开票日期确认
|
const onIssueDateConfirm = (e) => {
|
form.value.issueDate = formatDateToYMD(e.value)
|
pickerIssueDateValue.value = e.value
|
showIssueDatePicker.value = false;
|
};
|
|
// 录入日期确认
|
const onCreateTimeConfirm = (e) => {
|
form.value.createTime = formatDateToYMD(e.value)
|
pickerCreateTimeValue.value = e.value
|
showCreateTimePicker.value = false;
|
};
|
|
|
|
// 格式化日期
|
const formatDate = (date) => {
|
const year = date.getFullYear()
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
const day = String(date.getDate()).padStart(2, '0')
|
return `${year}-${month}-${day}`
|
}
|
|
// 获取产品列表
|
const getProductList = async () => {
|
try {
|
showLoadingToast('加载中...')
|
const res = await getSalesLedgerWithProducts({ id: editData.value.id, type: 1 })
|
productData.value = res.productData;
|
form.value = { ...res };
|
// 设置默认录入人
|
form.value.createUer = userStore.nickName || ''
|
|
// 设置默认日期
|
const today = new Date()
|
form.value.createTime = formatDate(today)
|
|
closeToast()
|
} catch (error) {
|
closeToast()
|
showToast('获取产品列表失败')
|
}
|
}
|
|
// 提交表单
|
const submitForm = async () => {
|
try {
|
submitting.value = true
|
|
// 验证产品数据
|
if (productData.value.length === 0) {
|
showToast('请先添加产品信息')
|
return
|
}
|
|
// 验证开票数据
|
const hasInvoiceData = productData.value.some(item => {
|
const num = parseFloat(item.currentInvoiceNum) || 0
|
const amount = parseFloat(item.currentInvoiceAmount) || 0
|
return num > 0 || amount > 0
|
})
|
|
if (!hasInvoiceData) {
|
showToast('请至少输入一个产品的开票信息')
|
return
|
}
|
|
const submitData = {
|
...form.value,
|
productList: productData.value
|
}
|
|
await invoiceRegistrationSave(submitData)
|
showToast('提交成功')
|
|
// 返回上一页
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
|
} catch (error) {
|
showToast('提交失败,请重试')
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
// 页面加载时初始化数据
|
onMounted(() => {
|
// 从页面参数或缓存中获取销售合同信息
|
const contractInfo = uni.getStorageSync('editData')
|
if (contractInfo) {
|
editData.value = JSON.parse(contractInfo);
|
const contract = JSON.parse(contractInfo)
|
form.value.salesContractNo = contract.salesContractNo || ''
|
form.value.customerName = contract.customerName || ''
|
form.value.salesman = contract.salesman || ''
|
form.value.projectName = contract.projectName || ''
|
|
// 获取产品列表
|
getProductList()
|
}
|
})
|
</script>
|
|
<style lang="scss">
|
@import '@/static/scss/form-common.scss';
|
</style>
|