From 424304d58e1acbe096fad794605906482c3a2ef7 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 19 八月 2025 16:42:51 +0800 Subject: [PATCH] 1.销售台账联调 2.开票登记开发联调 --- src/pages/sales/invoicingRegistration/add.vue | 537 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 537 insertions(+), 0 deletions(-) diff --git a/src/pages/sales/invoicingRegistration/add.vue b/src/pages/sales/invoicingRegistration/add.vue new file mode 100644 index 0000000..ee658e0 --- /dev/null +++ b/src/pages/sales/invoicingRegistration/add.vue @@ -0,0 +1,537 @@ +<template> + <view class="account-detail"> + <!-- 椤甸潰澶撮儴 --> + <van-nav-bar + title="鏂板寮�绁ㄧ櫥璁�" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> + + <!-- 琛ㄥ崟鍐呭 --> + <van-form @submit="submitForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> + <!-- 鍩烘湰淇℃伅 --> + <van-cell-group title="鍩烘湰淇℃伅" inset> + <van-field + v-model="form.salesContractNo" + label="閿�鍞悎鍚屽彿" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.customerName" + label="瀹㈡埛鍚嶇О" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.salesman" + label="涓氬姟鍛�" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.projectName" + label="椤圭洰鍚嶇О" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.createUer" + label="褰曞叆浜�" + readonly + placeholder="璇疯緭鍏ュ綍鍏ヤ汉" + /> + <van-field + v-model="form.createTime" + label="褰曞叆鏃ユ湡" + readonly + placeholder="璇烽�夋嫨褰曞叆鏃ユ湡" + @click="showCreateTimePicker = true" + /> + <van-field + v-model="form.invoiceNo" + label="鍙戠エ鍙风爜" + required + placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" + :rules="[{ required: true, message: '璇疯緭鍏ュ彂绁ㄥ彿鐮�' }]" + /> + <van-field + v-model="form.issueDate" + label="寮�绁ㄦ棩鏈�" + readonly + placeholder="璇烽�夋嫨寮�绁ㄦ棩鏈�" + required + @click="showIssueDatePicker = true" + :rules="[{ required: true, message: '璇烽�夋嫨寮�绁ㄦ棩鏈�' }]" + /> + </van-cell-group> + + <!-- 浜у搧淇℃伅 --> + <view class="product-section"> + <view class="section-header"> + <text class="section-title">浜у搧淇℃伅</text> + </view> + + <view v-if="productData.length === 0" class="empty-state"> + <van-empty description="鏆傛棤浜у搧鏁版嵁" /> + </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"> + <van-icon name="description" color="#2979ff" size="15" /> + <text class="product-productCategory">浜у搧 {{ index + 1 }}</text> + </view> + </view> + + <!-- 浜у搧淇℃伅琛ㄥ崟 --> + <view class="product-form"> + <van-field + v-model="item.productCategory" + label="浜у搧澶х被" + readonly + /> + <van-field + v-model="item.specificationModel" + label="瑙勬牸鍨嬪彿" + readonly + /> + <van-field + v-model="item.unit" + label="鍗曚綅" + readonly + /> + <van-field + v-model="item.quantity" + label="鏁伴噺" + readonly + /> + <van-field + v-model="item.taxRate" + label="绋庣巼(%)" + readonly + /> + <van-field + v-model="item.taxInclusiveUnitPrice" + label="鍚◣鍗曚环(鍏�)" + readonly + /> + <van-field + v-model="item.taxInclusiveTotalPrice" + label="鍚◣鎬讳环(鍏�)" + readonly + /> + <van-field + v-model="item.taxExclusiveTotalPrice" + label="涓嶅惈绋庢�讳环(鍏�)" + readonly + /> + + <!-- 鏈寮�绁ㄤ俊鎭� --> + <van-field + v-model="item.currentInvoiceNum" + label="鏈寮�绁ㄦ暟" + type="number" + placeholder="璇疯緭鍏ュ紑绁ㄦ暟閲�" + @blur="invoiceNumBlur(item)" + /> + <van-field + v-model="item.currentInvoiceAmount" + label="鏈寮�绁ㄩ噾棰�(鍏�)" + type="number" + placeholder="璇疯緭鍏ュ紑绁ㄩ噾棰�" + @blur="invoiceAmountBlur(item)" + /> + + <!-- 鏈紑绁ㄤ俊鎭� --> + <van-field + v-model="item.noInvoiceNum" + label="鏈紑绁ㄦ暟" + readonly + /> + <van-field + v-model="item.noInvoiceAmount" + label="鏈紑绁ㄩ噾棰�(鍏�)" + readonly + /> + </view> + </view> + </view> + </view> + + <!-- 鎻愪氦鎸夐挳 --> + <view class="footer-btns"> + <van-button class="cancel-btn" @click="goBack">鍙栨秷</van-button> + <van-button class="save-btn" native-type="submit" form-type="submit">淇濆瓨</van-button> + </view> + </van-form> + + <!-- 鏃ユ湡閫夋嫨鍣� --> + <van-popup v-model:show="showIssueDatePicker" position="bottom"> + <van-date-picker + v-model="currentIssueDate" + title="閫夋嫨寮�绁ㄦ棩鏈�" + @confirm="onIssueDateConfirm" + @cancel="showIssueDatePicker = false" + /> + </van-popup> + + <van-popup v-model:show="showCreateTimePicker" position="bottom"> + <van-date-picker + v-model="currentCreateTime" + title="閫夋嫨褰曞叆鏃ユ湡" + @confirm="onCreateTimeConfirm" + @cancel="showCreateTimePicker = false" + /> + </van-popup> + </view> +</template> + +<script setup> +import { ref, reactive, onMounted } from 'vue' +import { showToast, showLoadingToast, closeToast } from 'vant' +import { invoiceRegistrationSave } from '@/api/salesManagement/invoiceRegistration' +import useUserStore from '@/store/modules/user' +import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger"; + +const userStore = useUserStore() +const editData = ref(null); + +// 琛ㄥ崟寮曠敤 +const formRef = ref() + +// 琛ㄥ崟鏁版嵁 +let form = ref({ + salesContractNo: '', + customerName: '', + salesman: '', + projectName: '', + createUer: '', + issueDate: '', + createTime: '', + invoiceNo: '' +}) + +// 浜у搧鏁版嵁 +const productData = ref([]) + +// 鏃ユ湡閫夋嫨鍣ㄧ姸鎬� +const showIssueDatePicker = ref(false) +const showCreateTimePicker = ref(false) +const currentIssueDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) +const currentCreateTime = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) + +// 鎻愪氦鐘舵�� +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 = ({ selectedValues }) => { + console.log('selectedValues--', selectedValues) + form.value.issueDate = selectedValues.join('-'); + currentIssueDate.value = selectedValues; + showIssueDatePicker.value = false; +}; + +// 褰曞叆鏃ユ湡纭 +const onCreateTimeConfirm = (value) => { + try { + // 澶勭悊涓嶅悓鐨勫�兼牸寮� + let year, month, day; + + if (Array.isArray(value)) { + // 鏁扮粍鏍煎紡 [year, month, day] + [year, month, day] = value; + } else if (value && typeof value === 'object') { + // Date瀵硅薄鏍煎紡 + year = value.getFullYear(); + month = value.getMonth() + 1; + day = value.getDate(); + } else { + // 鍏朵粬鏍煎紡锛屼娇鐢ㄥ綋鍓嶆棩鏈� + const now = new Date(); + year = now.getFullYear(); + month = now.getMonth() + 1; + day = now.getDate(); + } + + form.value.createTime = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; + showCreateTimePicker.value = false; + } catch (error) { + console.error('鏃ユ湡澶勭悊閿欒:', error); + showToast('鏃ユ湡閫夋嫨澶辫触锛岃閲嶈瘯'); + } +} + +// 鏍煎紡鍖栨棩鏈� +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.name || '' + + // 璁剧疆榛樿鏃ユ湡 + 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 scoped lang="scss"> +.account-detail { + min-height: 100vh; + background: #f8f9fa; + padding-bottom: 5rem; +} + +.empty-state { + padding: 40px 0; +} + +.product-section { + background: #fff; + margin-top: 1rem; + padding: 1rem; + box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); +} + +.section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1rem; +} + +.section-title { + font-size: 1rem; + font-weight: 600; + color: #333; +} + +.product-list { + .product-card { + background: #FFFFFF; + box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); + border-radius: 0.5rem 0.5rem 0.5rem 0.5rem; + padding: 1rem 0.5rem 0 0.5rem; + position: relative; + margin-bottom: 1rem; + } +} + +.product-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 0.5rem 0.75rem 0.5rem; + border-bottom: 0.0625rem solid #e8e8e8; +} + +.product-title { + display: flex; + align-items: center; +} + +.product-productCategory { + margin-left: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + color: #333; +} + +.product-form { + margin-bottom: 1rem; +} +.footer-btns { + position: fixed; + left: 0; + right: 0; + bottom: 0; + background: #fff; + display: flex; + justify-content: space-around; + align-items: center; + padding: 0.75rem 0; + box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); + z-index: 1000; +} +.cancel-btn { + font-weight: 400; + font-size: 1rem; + color: #FFFFFF; + width: 6.375rem; + background: #C7C9CC; + box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); + border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; +} +.save-btn { + font-weight: 400; + font-size: 1rem; + color: #FFFFFF; + width: 14rem; + background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); + box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); + border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; +} +// 鍝嶅簲寮忚皟鏁� +@media (max-width: 768px) { + .submit-section { + padding: 12px; + } +} +</style> -- Gitblit v1.9.3