From 89cd3efd5dc533e6c8129d7d86dc74e1adf3d84c Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期三, 20 八月 2025 14:00:25 +0800 Subject: [PATCH] 1.回款登记页面开发账联调 --- src/pages/sales/invoiceLedger/detail.vue | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 277 insertions(+), 0 deletions(-) diff --git a/src/pages/sales/invoiceLedger/detail.vue b/src/pages/sales/invoiceLedger/detail.vue new file mode 100644 index 0000000..230564a --- /dev/null +++ b/src/pages/sales/invoiceLedger/detail.vue @@ -0,0 +1,277 @@ +<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 /> + <van-field v-model="form.customerName" label="瀹㈡埛鍚嶇О" readonly /> + <van-field v-model="form.invoiceNo" label="鍙戠エ鍙�" placeholder="璇疯緭鍏�" required :rules="[{ required: true, message: '璇疯緭鍏ュ彂绁ㄥ彿' }]" /> + <van-field v-model="form.invoiceTotal" label="鍙戠エ閲戦(鍏�)" type="number" placeholder="璇疯緭鍏�" required :rules="[{ required: true, message: '璇疯緭鍏ュ彂绁ㄩ噾棰�' }]" /> + <view class="tip-text" v-if="form.taxInclusiveTotalPrice">鍚堝悓鎬婚锛歿{ formatAmount(form.taxInclusiveTotalPrice) }} 鍏�</view> + <van-field v-model="form.invoicePerson" label="寮�绁ㄤ汉" readonly /> + <van-field v-model="form.invoiceDate" label="寮�绁ㄦ棩鏈�" readonly placeholder="璇烽�夋嫨" @click="showInvoiceDatePicker = true" required :rules="[{ required: true, message: '璇烽�夋嫨寮�绁ㄦ棩鏈�' }]" /> + </van-cell-group> + + <van-cell-group title="闄勪欢鏉愭枡锛堜粎鏀寔 pdf锛�" inset> + <van-uploader + accept=".pdf" + multiple + :after-read="afterReadUpload" + :before-read="beforeReadPdf" + > + <van-button class="upload-btn" icon="plus" type="primary" block>涓婁紶鏂囦欢</van-button> + </van-uploader> + <view class="uploaded-list" v-if="fileList.length"> + <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> + <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> + <van-button size="mini" type="danger" plain @click="removeUploaded(idx)">绉婚櫎</van-button> + </view> + </view> + </van-cell-group> + + <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="showInvoiceDatePicker" position="bottom"> + <van-date-picker + v-model="currentInvoiceDate" + title="閫夋嫨寮�绁ㄦ棩鏈�" + @confirm="onInvoiceDateConfirm" + @cancel="showInvoiceDatePicker = false" + /> + </van-popup> + </view> +</template> + +<script setup> +import { ref, onMounted } from 'vue' +import { showToast, showLoadingToast, closeToast } from 'vant' +import dayjs from 'dayjs' +import useUserStore from '@/store/modules/user' +import { getToken } from '@/utils/auth' +import { invoiceLedgerProductInfo, invoiceLedgerSaveOrUpdate } from '@/api/salesManagement/invoiceLedger.js' +import config from '@/config.js' + +const userStore = useUserStore() + +const formRef = ref() +let form = ref({ + salesLedgerId: '', + customerId: '', + invoiceNo: '', + invoiceTotal: '', + taxRate: '', + invoicePerson: '', + invoiceDate: '', + customerName: '', + fileList: [], + createTime: '', + taxInclusiveTotalPrice: '' +}) +const fileList = ref([]) +const currentId = ref('') + +// 鏃ユ湡閫夋嫨 +const showInvoiceDatePicker = ref(false) +const currentInvoiceDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) + +const goBack = () => { + uni.removeStorageSync('invoiceLedgerEditRow'); + uni.navigateBack() +} + +const formatAmount = (val) => { + if (val === undefined || val === null || val === '') return '0.00' + const num = Number(val) + if (Number.isNaN(num)) return '0.00' + return num.toFixed(2) +} + +const onInvoiceDateConfirm = ({ selectedValues }) => { + form.value.invoiceDate = selectedValues.join('-') + currentInvoiceDate.value = selectedValues + showInvoiceDatePicker.value = false +} + +// 涓婁紶鍓嶆牎楠岋紙鍏煎 Vant Uploader 鐨� file/fileList 缁撴瀯锛� +const beforeReadPdf = (file) => { + const items = Array.isArray(file) ? file : [file] + for (const it of items) { + const raw = it?.file || it + const fileName = raw?.name || it?.name || '' + const ext = fileName.split('.').pop()?.toLowerCase() + const sizeOk = (raw?.size || 0) <= 10 * 1024 * 1024 + if (ext !== 'pdf') { + showToast('浠呮敮鎸乸df鏂囦欢') + return false + } + if (!sizeOk) { + showToast('涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB') + return false + } + } + return true +} + +const uploadSingleFile = async (fileObj) => { + return new Promise((resolve, reject) => { + showLoadingToast({ message: '姝e湪涓婁紶...' }) + const baseUrl = config.baseUrl + '/invoiceLedger/uploadFile' + + const filePath = fileObj?.url || fileObj?.tempFilePath || fileObj?.file?.path + if (filePath) { + uni.uploadFile({ + url: baseUrl, + filePath, + name: 'file', + header: { Authorization: 'Bearer ' + getToken() }, + success: (res) => { + closeToast() + try { + const data = JSON.parse(res.data || '{}') + if (data.code === 200) { + resolve(data.data) + } else { + reject(new Error(data.msg || '涓婁紶澶辫触')) + } + } catch (err) { + reject(err) + } + }, + fail: (err) => { + closeToast() + reject(err) + } + }) + return + } + + // H5: 浣跨敤鍘熷 File锛坕nput 閫夋嫨锛� + const rawFile = fileObj?.file + if (rawFile) { + // uni.uploadFile 鍦� H5 涓嶆敮鎸佸師鐢� File 瀵硅薄锛岃繖閲岀敤 fetch 鍙戦�� FormData + const formData = new FormData() + formData.append('file', rawFile, rawFile.name || 'file.pdf') + formData.append('salesLedgerId', form.value.salesLedgerId || currentId.value || '') + fetch(baseUrl, { + method: 'POST', + headers: { Authorization: 'Bearer ' + getToken() }, + body: formData + }).then(async (res) => { + closeToast() + const data = await res.json() + if (data.code === 200) { + resolve(data.data) + } else { + reject(new Error(data.msg || '涓婁紶澶辫触')) + } + }).catch((err) => { + closeToast() + reject(err) + }) + return + } + + closeToast() + reject(new Error('鏈壘鍒板彲涓婁紶鐨勬枃浠�')) + }) +} + +const afterReadUpload = async (file) => { + try { + const files = Array.isArray(file) ? file : file?.file ? [file] : [file] + for (const f of files) { + const uploaded = await uploadSingleFile(f) + fileList.value.push(uploaded) + } + showToast('涓婁紶鎴愬姛') + } catch (e) { + showToast('涓婁紶澶辫触') + } +} + +const removeUploaded = (index) => { + fileList.value.splice(index, 1) +} + +const getFileNameFromUrl = (url) => { + try { if (!url) return ''; return decodeURIComponent(url.split('/').pop()) } catch (e) { return url } +} + +const loadDetail = async (id) => { + try { + showLoadingToast({ message: '鍔犺浇涓�...' }) + const res = await invoiceLedgerProductInfo({ id }) + const data = res?.data || res + form.value = { ...data } + fileList.value = data?.fileList || [] + if (!form.value.invoicePerson) { + form.value.invoicePerson = userStore.nickName + } + if (!form.value.invoiceDate) { + form.value.invoiceDate = dayjs().format('YYYY-MM-DD') + } + closeToast() + } catch (e) { + closeToast() + showToast('鍔犺浇澶辫触') + } +} + +const submitForm = async () => { + try { + if (!form.value.invoiceNo) { showToast('璇疯緭鍏ュ彂绁ㄥ彿'); return } + if (!form.value.invoiceTotal) { showToast('璇疯緭鍏ュ彂绁ㄩ噾棰�'); return } + if (!form.value.invoiceDate) { showToast('璇烽�夋嫨寮�绁ㄦ棩鏈�'); return } + showLoadingToast({ message: '鎻愪氦涓�...' }) + form.value.fileList = fileList.value + await invoiceLedgerSaveOrUpdate(form.value) + closeToast() + showToast('鎻愪氦鎴愬姛') + setTimeout(() => { uni.navigateBack() }, 800) + } catch (e) { + closeToast() + showToast('鎻愪氦澶辫触锛岃閲嶈瘯') + } +} + +onMounted(() => { + const rowStr = uni.getStorageSync('invoiceLedgerEditRow') + if (rowStr) { + try { + const row = JSON.parse(rowStr) + currentId.value = row.id + loadDetail(currentId.value) + } catch (e) { + // ignore + } + } +}) +</script> + +<style scoped lang="scss"> +.account-detail { + min-height: 100vh; + background: #f8f9fa; + padding-bottom: 5rem; +} +.uploaded-list { padding: 8px 16px 0 16px; } +.uploaded-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f5f5f5; } +.file-name { font-size: 12px; color: #333; margin-right: 8px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } +.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; } +</style> + -- Gitblit v1.9.3