From 5d51aeded717c667a22096174168e4e5e59bde39 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期五, 22 八月 2025 15:38:57 +0800 Subject: [PATCH] 1.来票登记开发联调 --- src/pages/index.vue | 5 src/pages/procurementManagement/invoiceEntry/add.vue | 542 +++++++++++++++++++++++ src/pages.json | 21 src/components/PageHeader.vue | 2 src/pages/procurementManagement/invoiceEntry/index.vue | 419 ++++++++++++++++++ src/pages/sales/invoicingRegistration/index.vue | 32 - src/pages/procurementManagement/invoiceEntry/view.vue | 311 +++++++++++++ 7 files changed, 1,304 insertions(+), 28 deletions(-) diff --git a/src/components/PageHeader.vue b/src/components/PageHeader.vue index 6d50e54..58acaca 100644 --- a/src/components/PageHeader.vue +++ b/src/components/PageHeader.vue @@ -48,7 +48,7 @@ props.customBack(); } else { emit('back'); - uni.navigateBack(); + // uni.navigateBack(); } }; </script> diff --git a/src/pages.json b/src/pages.json index 867ffb0..190d3a9 100644 --- a/src/pages.json +++ b/src/pages.json @@ -162,6 +162,27 @@ } }, { + "path": "pages/procurementManagement/invoiceEntry/index", + "style": { + "navigationBarTitleText": "鏉ョエ鐧昏", + "navigationStyle": "custom" + } + }, + { + "path": "pages/procurementManagement/invoiceEntry/add", + "style": { + "navigationBarTitleText": "鏂板鏉ョエ鐧昏", + "navigationStyle": "custom" + } + }, + { + "path": "pages/procurementManagement/invoiceEntry/view", + "style": { + "navigationBarTitleText": "鏉ョエ鐧昏璇︽儏", + "navigationStyle": "custom" + } + }, + { "path": "pages/common/webview/index", "style": { "navigationBarTitleText": "娴忚缃戦〉" diff --git a/src/pages/index.vue b/src/pages/index.vue index 9578b19..c98e2cc 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -323,6 +323,11 @@ url: '/pages/procurementManagement/procurementLedger/index' }); break; + case '鏉ョエ鐧昏': + uni.navigateTo({ + url: '/pages/procurementManagement/invoiceEntry/index' + }); + break; case '鍗忓悓瀹℃壒': uni.navigateTo({ url: '/pages/cooperativeOffice/collaborativeApproval/index' diff --git a/src/pages/procurementManagement/invoiceEntry/add.vue b/src/pages/procurementManagement/invoiceEntry/add.vue new file mode 100644 index 0000000..6935e92 --- /dev/null +++ b/src/pages/procurementManagement/invoiceEntry/add.vue @@ -0,0 +1,542 @@ +<template> + <view class="account-detail"> + <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 --> + <PageHeader title="鏂板鏉ョエ鐧昏" @back="goBack" /> + + <!-- 琛ㄥ崟鍐呭 --> + <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.purchaseLedgerNo" + label="閲囪喘鍚堝悓鍙�" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.salesContractNo" + label="閿�鍞悎鍚屽彿" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.supplierName" + label="渚涘簲鍟嗗悕绉�" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.projectName" + label="椤圭洰鍚嶇О" + readonly + placeholder="鑷姩濉厖" + /> + <van-field + v-model="form.issUer" + label="褰曞叆浜�" + readonly + placeholder="璇疯緭鍏ュ綍鍏ヤ汉" + /> + <van-field + v-model="form.enterDate" + label="褰曞叆鏃ユ湡" + readonly + placeholder="璇烽�夋嫨褰曞叆鏃ユ湡" + @click="showCreateTimePicker = true" + /> + <van-field + v-model="form.invoiceNumber" + label="鍙戠エ鍙风爜" + required + placeholder="璇疯緭鍏ュ彂绁ㄥ彿鐮�" + :rules="[{ required: true, message: '璇疯緭鍏ュ彂绁ㄥ彿鐮�' }]" + /> + <van-field + v-model="form.invoiceAmount" + label="鍙戠エ閲戦(鍏�)" + required + readonly + 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.ticketsNum" + label="鏈鏉ョエ鏁�" + type="number" + placeholder="璇疯緭鍏ユ潵绁ㄦ暟閲�" + @blur="invoiceNumBlur(item)" + /> + <van-field + v-model="item.ticketsAmount" + label="鏈鏉ョエ閲戦(鍏�)" + type="number" + placeholder="璇疯緭鍏ユ潵绁ㄩ噾棰�" + @blur="invoiceAmountBlur(item)" + /> + + <!-- 鏈潵绁ㄤ俊鎭� --> + <van-field + v-model="item.futureTickets" + label="鏈潵绁ㄦ暟" + readonly + /> + <van-field + v-model="item.futureTicketsAmount" + 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, onMounted } from 'vue' +import { showToast, showLoadingToast, closeToast } from 'vant' +import useUserStore from '@/store/modules/user' +import {addOrUpdateRegistration, getPurchaseNoById} from "@/api/procurementManagement/invoiceEntry"; +import {getInfo} from "@/api/procurementManagement/invoiceEntry.js"; + +const userStore = useUserStore() +const editData = ref(null); + +// 琛ㄥ崟寮曠敤 +const formRef = ref() + +// 琛ㄥ崟鏁版嵁 +let form = ref({ + purchaseLedgerNo: '', + salesContractNo: '', + supplierName: '', + projectName: '', + issUer: '', + issueDate: '', + enterDate: '', + invoiceAmount: '', + invoiceNumber: '' +}) + +// 浜у搧鏁版嵁 +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.ticketsNum || row.ticketsNum === "") { + row.ticketsNum = 0; + } + if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { + showToast('鏈鏉ョエ鏁颁笉寰楀ぇ浜庢湭鏉ョエ鏁�'); + row.ticketsNum = 0; + return; + } + // 璁$畻鏈鏉ョエ閲戦 + row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) + // 璁$畻鏈潵绁ㄦ暟 + row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) + // 璁$畻鏈潵绁ㄩ噾棰� + row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) + calculateinvoiceAmount(); +} + +// 鏉ョエ閲戦鍙樺寲澶勭悊 +const invoiceAmountBlur = (row) => { + if (!row.ticketsAmount) { + row.ticketsAmount = 0; + } + // 璁$畻鏄惁瓒呰繃鏉ョエ鎬婚噾棰� + if (row.ticketsAmount > row.tempFutureTicketsAmount) { + showToast('鏈鏉ョエ閲戦涓嶅緱澶т簬鏈潵绁ㄩ噾棰�'); + row.ticketsAmount = 0; + } + // 璁$畻鏈鏉ョエ鏁� + row.ticketsNum = Number( + (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) + ); + // 璁$畻鏈潵绁ㄦ暟 + row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) + // 璁$畻鏈潵绁ㄩ噾棰� + row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) + calculateinvoiceAmount(); +} + +const calculateinvoiceAmount = () => { + let invoiceAmountTotal = 0; + productData.value.forEach((item) => { + if (item.ticketsAmount) { + invoiceAmountTotal += Number(item.ticketsAmount); + } + }); + form.value.invoiceAmount = invoiceAmountTotal.toFixed(2); +}; + +// 鏉ョエ鏃ユ湡纭 +const onIssueDateConfirm = ({ 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.enterDate = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; + form.value.issueDate = `${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 getPurchaseNoById({ id: editData.value.id }) + form.value.purchaseLedgerNo = res.data.purchaseContractNumber; + form.value.invoiceAmount = res.data.invoiceAmount; + form.value.invoiceNumber = res.data.invoiceNumber; + const data = await getInfo({ id: editData.value.id }); + productData.value = data.data.productData; + form.value.salesContractNo = data.data.salesContractNo; + form.value.projectName = data.data.projectName; + form.value.supplierName = data.data.supplierName; + form.value.productData = data.data.productData; + // 璁剧疆榛樿褰曞叆浜� + form.value.issUer = userStore.nickName + + // 璁剧疆榛樿鏃ユ湡 + const today = new Date() + form.value.enterDate = formatDate(today) + form.value.issueDate = 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.ticketsNum) || 0 + const amount = parseFloat(item.ticketsAmount) || 0 + return num > 0 || amount > 0 + }) + + if (!hasInvoiceData) { + showToast('璇疯嚦灏戣緭鍏ヤ竴涓骇鍝佺殑鏉ョエ淇℃伅') + return + } + + const submitData = { + ...form.value, + productData: productData.value + } + + await addOrUpdateRegistration(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.purchaseLedgerNo = contract.purchaseLedgerNo || '' + form.value.salesContractNo = contract.salesContractNo || '' + form.value.supplierName = contract.supplierName || '' + form.value.projectName = contract.projectName || '' + form.value.invoiceAmount = contract.invoiceAmount || '' + form.value.invoiceNumber = contract.invoiceNumber || '' + form.value.purchaseLedgerId = contract.id || '' + + // 鑾峰彇浜у搧鍒楄〃 + 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> diff --git a/src/pages/procurementManagement/invoiceEntry/index.vue b/src/pages/procurementManagement/invoiceEntry/index.vue new file mode 100644 index 0000000..48ac313 --- /dev/null +++ b/src/pages/procurementManagement/invoiceEntry/index.vue @@ -0,0 +1,419 @@ +<template> + <view class="sales-account"> + <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 --> + <PageHeader title="鏉ョエ鐧昏" @back="goBack" /> + + <!-- 鎼滅储鍜岀瓫閫夊尯鍩� --> + <view class="search-filter-section"> + <view class="search-bar"> + <view class="search-input"> + <input + class="search-text" + placeholder="璇疯緭鍏ラ噰璐悎鍚屽彿/渚涘簲鍟嗗悕绉�" + v-model="searchKeyword" + /> + </view> + <view class="filter-button" @click="getList"> + <up-icon name="search" size="24" color="#999"></up-icon> + </view> + </view> + </view> + + <!-- 閲囪喘鍙拌处鐎戝竷娴� --> + <view class="ledger-list" v-if="ledgerList.length > 0"> + <view v-for="(item, index) in ledgerList" :key="index"> + <view class="ledger-item"> + <view class="item-header"> + <view class="item-left"> + <view class="document-icon"> + <up-icon name="file-text" size="16" color="#ffffff"></up-icon> + </view> + <text class="item-id">{{ item.purchaseContractNumber }}</text> + </view> + </view> + <up-divider></up-divider> + + <view class="item-details"> + <view class="detail-row"> + <text class="detail-label">閿�鍞悎鍚屽彿</text> + <text class="detail-value">{{ item.salesContractNo }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">渚涘簲鍟嗗悕绉�</text> + <text class="detail-value">{{ item.supplierName }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">椤圭洰鍚嶇О</text> + <text class="detail-value">{{ item.projectName }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">鍚堝悓閲戦(鍏�)</text> + <text class="detail-value highlight">{{ item.contractAmount }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">宸插紑绁ㄩ噾棰�(鍏�)</text> + <text class="detail-value highlight">{{ item.receiptPaymentAmount }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">寰呭紑绁ㄩ噾棰�(鍏�)</text> + <text class="detail-value redlight">{{ item.unReceiptPaymentAmount }}</text> + </view> + </view> + + <!-- 鎿嶄綔鎸夐挳鍖哄煙 --> + <view class="action-buttons"> + <van-button + type="primary" + size="small" + @click="handleAddInvoice(item)" + class="action-btn" + :disabled="item.unReceiptPaymentAmount == 0" + > + 鏂板寮�绁� + </van-button> + <van-button + type="default" + size="small" + @click="handleViewDetail(item)" + class="action-btn" + > + 鏌ョ湅璇︽儏 + </van-button> + </view> + </view> + </view> + </view> + <view v-else class="no-data"> + <text>鏆傛棤閲囪喘鍙拌处鏁版嵁</text> + </view> + </view> +</template> + +<script setup> +import { ref } from 'vue'; +import { onShow } from '@dcloudio/uni-app'; +import useUserStore from "@/store/modules/user"; +import {gePurchaseListPage} from "@/api/procurementManagement/invoiceEntry"; +const userStore = useUserStore() + +// 鎼滅储鍏抽敭璇� +const searchKeyword = ref(''); + +// 閲囪喘鍙拌处鏁版嵁 +const ledgerList = ref([]); + +// 杩斿洖涓婁竴椤� +const goBack = () => { + uni.navigateBack(); +}; +// 鏌ヨ鍒楄〃 +const getList = () => { + const page = { + current: -1, + size: -1 + } + gePurchaseListPage({...page}).then((res) => { + ledgerList.value = res.data.records; + }).catch(() => { + // tableLoading.value = false; + }); +}; + +// 澶勭悊鏂板鏉ョエ +const handleAddInvoice = (item) => { + try { + // 瀛樺偍閫変腑鐨勫悎鍚屼俊鎭� + uni.setStorageSync('editData', JSON.stringify(item)); + // 璺宠浆鍒版柊澧炴潵绁ㄩ〉闈� + uni.navigateTo({ + url: '/pages/procurementManagement/invoiceEntry/add' + }); + } catch (error) { + console.error('澶勭悊鏂板鏉ョエ澶辫触:', error); + uni.showToast({ + title: '鎿嶄綔澶辫触锛岃閲嶈瘯', + icon: 'error' + }); + } +}; + +// 澶勭悊鏌ョ湅璇︽儏 +const handleViewDetail = (item) => { + try { + // 瀛樺偍鏁版嵁 + uni.setStorageSync('editData', JSON.stringify(item)); + + // 璺宠浆鍒拌鎯呴〉闈� + uni.navigateTo({ + url: '/pages/procurementManagement/invoiceEntry/view' + }); + } catch (error) { + console.error('澶勭悊鏌ョ湅璇︽儏澶辫触:', error); + uni.showToast({ + title: '鎿嶄綔澶辫触锛岃閲嶈瘯', + icon: 'error' + }); + } +}; + +onShow(() => { + // 椤甸潰鏄剧ず鏃跺埛鏂板垪琛� + getList(); +}); +</script> + +<style scoped lang="scss"> +.u-divider { + margin: 0 !important; +} +.sales-account { + min-height: 100vh; + background: #f8f9fa; + position: relative; +} + +.page-header { + background: #ffffff; + padding: 16px 20px; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid #f0f0f0; + position: sticky; + /* 鍏煎 iOS 鍒樻捣/鐏靛姩宀涘畨鍏ㄥ尯 */ + padding-top: env(safe-area-inset-top); + top: 0; + z-index: 100; +} + +.header-left { + display: flex; + align-items: center; + gap: 8px; +} + +.nav-icon { + width: 24px; + height: 24px; + background: #2979ff; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; +} + +.nav-text { + font-size: 14px; + color: #2979ff; + font-weight: 500; +} + +.header-center { + flex: 1; + display: flex; + justify-content: center; + align-items: center; + position: absolute; + left: 0; + right: 0; + pointer-events: none; +} + +.page-title { + font-size: 18px; + font-weight: 600; + color: #333; + pointer-events: auto; +} + +.header-right { + display: flex; + align-items: center; +} + +.status-bar { + display: flex; + align-items: center; + gap: 4px; +} + +.signal, .wifi, .battery { + width: 16px; + height: 8px; + background: #333; + border-radius: 2px; +} + +.search-filter-section { + padding: 10px 20px; + background: #ffffff; +} + +.search-bar { + display: flex; + align-items: center; + gap: 12px; +} + +.search-input { + flex: 1; + background: #f5f5f5; + border-radius: 24px; + padding: 10px 16px; + display: flex; + align-items: center; + gap: 8px; +} + +.search-text { + flex: 1; + font-size: 14px; + color: #333; + background: transparent; + border: none; + outline: none; +} + +.search-text::placeholder { + color: #999; +} + +.filter-button { + width: 40px; + height: 40px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; +} + +.ledger-list { + padding: 20px; +} + +.ledger-item { + background: #ffffff; + border-radius: 12px; + margin-bottom: 16px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + padding: 0 16px; +} + +.item-header { + padding: 16px 0; + display: flex; + align-items: center; + justify-content: space-between; +} + +.item-left { + display: flex; + align-items: center; + gap: 8px; +} + +.document-icon { + width: 24px; + height: 24px; + background: #2979ff; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; +} + +.item-id { + font-size: 14px; + color: #333; + font-weight: 500; +} + +.item-tag { + background: #4caf50; + border-radius: 4px; + padding: 2px 4px; +} + +.tag-text { + font-size: 11px; + color: #ffffff; + font-weight: 500; +} + +.item-details { + padding: 16px 0; +} + +.detail-row { + display: flex; + align-items: flex-end; + justify-content: space-between; + margin-bottom: 8px; + + &:last-child { + margin-bottom: 0; + } +} +.detail-info { + margin-top: 10px; + display: flex; + align-items: flex-start; + justify-content: space-between; +} + +.detail-label { + font-size: 12px; + color: #777777; + min-width: 60px; +} + +.detail-value { + font-size: 12px; + color: #000000; + text-align: right; + flex: 1; + margin-left: 16px; +} + +.detail-value.highlight { + color: #2979ff; + font-weight: 500; +} +.detail-value.redlight { + color: red; + font-weight: 500; +} + +.action-buttons { + display: flex; + gap: 12px; + padding: 0 0 16px 0; + justify-content: space-between; +} + +.action-btn { + flex: 1; +} + +.no-data { + padding: 40px 0; + text-align: center; + color: #999; +} + +.fab-button { + position: fixed; + bottom: 30px; + right: 30px; + width: 56px; + height: 56px; + background: #2979ff; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); + z-index: 1000; +} +</style> diff --git a/src/pages/procurementManagement/invoiceEntry/view.vue b/src/pages/procurementManagement/invoiceEntry/view.vue new file mode 100644 index 0000000..ac94304 --- /dev/null +++ b/src/pages/procurementManagement/invoiceEntry/view.vue @@ -0,0 +1,311 @@ +<template> + <view class="account-view"> + <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 --> + <PageHeader title="鏉ョエ鐧昏璇︽儏" @back="goBack" /> + + <!-- 鍩烘湰淇℃伅灞曠ず --> + <view class="info-section"> + <view class="section-title">鍩烘湰淇℃伅</view> + <view class="info-grid"> + <view class="info-item"> + <text class="info-label">閲囪喘鍚堝悓鍙�</text> + <text class="info-value">{{ form.purchaseContractNumber }}</text> + </view> + <view class="info-item"> + <text class="info-label">閿�鍞悎鍚屽彿</text> + <text class="info-value">{{ form.salesContractNo }}</text> + </view> + <view class="info-item"> + <text class="info-label">渚涘簲鍟嗗悕绉�</text> + <text class="info-value">{{ form.supplierName }}</text> + </view> + <view class="info-item"> + <text class="info-label">椤圭洰鍚嶇О</text> + <text class="info-value">{{ form.projectName }}</text> + </view> + <view class="info-item"> + <text class="info-label">鍚堝悓閲戦(鍏�)</text> + <text class="info-value highlight">{{ form.contractAmount }}</text> + </view> + <view class="info-item"> + <text class="info-label">宸叉潵绁ㄩ噾棰�(鍏�)</text> + <text class="info-value highlight">{{ form.receiptPaymentAmount }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈潵绁ㄩ噾棰�(鍏�)</text> + <text class="info-value redlight">{{ form.unReceiptPaymentAmount }}</text> + </view> + </view> + </view> + + <!-- 浜у搧淇℃伅灞曠ず --> + <view class="product-section" v-if="productData && productData.length > 0"> + <view class="section-title">浜у搧淇℃伅</view> + <view class="product-card" v-for="(product, idx) in productData" :key="idx"> + <view class="product-header"> + <view class="product-title"> + <van-icon name="description" color="#2979ff" size="15" /> + <text class="product-productCategory">浜у搧 {{ idx + 1 }}</text> + </view> + </view> + + <view class="product-info"> + <view class="info-grid"> + <view class="info-item"> + <text class="info-label">浜у搧澶х被</text> + <text class="info-value">{{ product.productCategory }}</text> + </view> + <view class="info-item"> + <text class="info-label">瑙勬牸鍨嬪彿</text> + <text class="info-value">{{ product.specificationModel }}</text> + </view> + <view class="info-item"> + <text class="info-label">鍗曚綅</text> + <text class="info-value">{{ product.unit }}</text> + </view> + <view class="info-item"> + <text class="info-label">绋庣巼(%)</text> + <text class="info-value">{{ product.taxRate }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏁伴噺</text> + <text class="info-value highlight">{{ product.quantity }}</text> + </view> + <view class="info-item"> + <text class="info-label">鍚◣鍗曚环(鍏�)</text> + <text class="info-value highlight">{{ product.taxInclusiveUnitPrice }}</text> + </view> + <view class="info-item"> + <text class="info-label">鍚◣鎬讳环(鍏�)</text> + <text class="info-value highlight">{{ product.taxInclusiveTotalPrice }}</text> + </view> + <view class="info-item"> + <text class="info-label">涓嶅惈绋庢�讳环(鍏�)</text> + <text class="info-value highlight">{{ product.taxExclusiveTotalPrice }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏉ョエ鏁�</text> + <text class="info-value highlight">{{ product.ticketsNum }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏉ョエ閲戦(鍏�)</text> + <text class="info-value highlight">{{ product.ticketsAmount }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈潵绁ㄦ暟</text> + <text class="info-value highlight">{{ product.futureTickets }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈潵绁ㄩ噾棰�(鍏�)</text> + <text class="info-value redlight">{{ product.futureTicketsAmount }}</text> + </view> + </view> + </view> + </view> + </view> + + <!-- 鏃犱骇鍝佷俊鎭彁绀� --> + <view class="no-product" v-else> + <text>鏆傛棤浜у搧淇℃伅</text> + </view> + </view> +</template> + +<script setup> +import { onMounted, ref } from 'vue'; +import {getPurchaseById} from "@/api/procurementManagement/procurementLedger"; + +// 琛ㄥ崟鏁版嵁 +const form = ref({ + id: '', + purchaseContractNumber: '', + salesContractNo: '', + customerId: '', + supplierName: '', + projectName: '', + executionDate: '', + contractAmount: '', + receiptPaymentAmount: '', + unReceiptPaymentAmount: '', + salesman: '' +}); + +// 浜у搧鏁版嵁 +const productData = ref([]); + +// 缂栬緫鏁版嵁 +const editData = ref(null); + +// 杩斿洖涓婁竴椤� +const goBack = () => { + // 娓呯悊鏈湴瀛樺偍鐨勬暟鎹� + uni.removeStorageSync('editData'); + uni.navigateBack(); +}; + +// 濉厖琛ㄥ崟鏁版嵁 +const fillFormData = () => { + if (!editData.value) return; + + // 鑾峰彇瀹屾暣鐨勪骇鍝佷俊鎭� + getPurchaseById({ id: editData.value.id, type: 2 }).then((res) => { + productData.value = res.productData || []; + // 濉厖鍩烘湰淇℃伅 + form.value.purchaseContractNumber = editData.value.purchaseContractNumber || ''; + form.value.salesContractNo = editData.value.salesContractNo || ''; + form.value.supplierName = editData.value.supplierName || ''; + form.value.projectName = editData.value.projectName || ''; + form.value.executionDate = editData.value.executionDate || ''; + form.value.contractAmount = editData.value.contractAmount || 0; + form.value.salesman = editData.value.salesman || ''; + form.value.receiptPaymentAmount = editData.value.receiptPaymentAmount || 0; + form.value.unReceiptPaymentAmount = editData.value.unReceiptPaymentAmount || 0; + }); +}; + +onMounted(() => { + // 鑾峰彇缂栬緫鏁版嵁骞跺~鍏呰〃鍗� + const editDataStr = uni.getStorageSync('editData'); + if (editDataStr) { + try { + editData.value = JSON.parse(editDataStr); + // 浣跨敤 nextTick 纭繚鏁版嵁鍔犺浇瀹屾垚鍚庡啀濉厖 + setTimeout(() => { + fillFormData(); + }, 100); + } catch (error) { + console.error('瑙f瀽缂栬緫鏁版嵁澶辫触:', error); + } + } +}); +</script> + +<style scoped lang="scss"> +.account-view { + min-height: 100vh; + background: #f8f9fa; + padding-bottom: 2rem; +} + +.header { + display: flex; + align-items: center; + background: #fff; + padding: 1rem 1.25rem; + border-bottom: 0.0625rem solid #f0f0f0; + position: sticky; + top: 0; + z-index: 100; + /* 鍏煎 iOS 鍒樻捣/鐏靛姩宀涘畨鍏ㄥ尯 */ + padding-top: env(safe-area-inset-top); +} + +.title { + flex: 1; + text-align: center; + font-size: 1.125rem; + font-weight: 600; + color: #333; +} + +.info-section { + background: #fff; + margin: 1rem; + padding: 1rem; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); +} + +.section-title { + font-size: 1rem; + font-weight: 600; + color: #333; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 0.0625rem solid #e8e8e8; +} + +.info-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.75rem; +} + +.info-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.info-label { + font-size: 0.75rem; + color: #666; + font-weight: 400; +} + +.info-value { + font-size: 0.875rem; + color: #333; + font-weight: 500; +} + +.info-value.highlight { + color: #2979ff; + font-weight: 600; +} +.info-value.redlight { + color: red; + font-weight: 600; +} + +.product-section { + background: #fff; + margin: 1rem; + padding: 1rem; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); +} + +.product-card { + background: #f8f9fa; + border-radius: 0.5rem; + padding: 1rem; + margin-bottom: 1rem; +} + +.product-card:last-child { + margin-bottom: 0; +} + +.product-header { + display: flex; + align-items: center; + padding-bottom: 0.75rem; + border-bottom: 0.0625rem solid #e8e8e8; + margin-bottom: 1rem; +} + +.product-title { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.product-productCategory { + font-size: 0.875rem; + font-weight: 500; + color: #333; +} + +.product-info .info-grid { + grid-template-columns: 1fr 1fr; + gap: 0.5rem; +} + +.no-product { + text-align: center; + padding: 2rem; + color: #999; + font-size: 0.875rem; +} +</style> diff --git a/src/pages/sales/invoicingRegistration/index.vue b/src/pages/sales/invoicingRegistration/index.vue index 4d2a79a..2f4c344 100644 --- a/src/pages/sales/invoicingRegistration/index.vue +++ b/src/pages/sales/invoicingRegistration/index.vue @@ -30,9 +30,6 @@ </view> <text class="item-id">{{ item.salesContractNo }}</text> </view> - <!-- <view class="item-tag">--> - <!-- <text class="tag-text">{{ item.recorder }}</text>--> - <!-- </view>--> </view> <up-divider></up-divider> @@ -71,16 +68,16 @@ <view class="action-buttons"> <van-button type="primary" - size="small" + size="small" @click="handleAddInvoice(item)" class="action-btn" - :disabled="item.entryPerson != userStore.id || item.noInvoiceAmountTotal == 0" + :disabled="item.noInvoiceAmountTotal == 0" > 鏂板寮�绁� </van-button> - <van-button - type="default" - size="small" + <van-button + type="default" + size="small" @click="handleViewDetail(item)" class="action-btn" > @@ -93,11 +90,6 @@ <view v-else class="no-data"> <text>鏆傛棤閿�鍞彴璐︽暟鎹�</text> </view> - - <!-- 娴姩鎿嶄綔鎸夐挳 --> - <!-- <view class="fab-button" @click="handleInfo('add')"> - <up-icon name="plus" size="24" color="#ffffff"></up-icon> - </view> --> </view> </template> @@ -114,11 +106,6 @@ // 閿�鍞彴璐︽暟鎹� const ledgerList = ref([]); const total = ref(0); - -// 鍚堝悓閫夋嫨鍣ㄧ浉鍏� -const contractList = ref([]); -const contractLoading = ref(false); -const contractFinished = ref(false); // 杩斿洖涓婁竴椤� const goBack = () => { @@ -141,15 +128,6 @@ // 澶勭悊鏂板寮�绁� const handleAddInvoice = (item) => { try { - // 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳芥柊澧炲紑绁� - if (item.entryPerson != userStore.id) { - uni.showToast({ - title: '鍙湁褰曞叆浜烘墠鑳芥柊澧炲紑绁�', - icon: 'none' - }); - return; - } - // 瀛樺偍閫変腑鐨勫悎鍚屼俊鎭� uni.setStorageSync('editData', JSON.stringify(item)); -- Gitblit v1.9.3