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/index.vue | 5 src/pages.json | 23 src/pages/sales/invoicingRegistration/add.vue | 537 ++++++++++++++++++++++ src/pages/sales/salesAccount/view.vue | 12 src/pages/sales/salesAccount/detail.vue | 12 src/pages/sales/invoicingRegistration/view.vue | 325 +++++++++++++ src/pages/sales/invoicingRegistration/index.vue | 448 ++++++++++++++++++ src/pages/sales/salesAccount/index.vue | 20 8 files changed, 1,362 insertions(+), 20 deletions(-) diff --git a/src/pages.json b/src/pages.json index 928af20..d14e8ad 100644 --- a/src/pages.json +++ b/src/pages.json @@ -71,6 +71,27 @@ } }, { + "path": "pages/sales/invoicingRegistration/index", + "style": { + "navigationBarTitleText": "寮�绁ㄧ櫥璁�", + "navigationStyle": "custom" + } + }, + { + "path": "pages/sales/invoicingRegistration/add", + "style": { + "navigationBarTitleText": "鏂板寮�绁ㄧ櫥璁�", + "navigationStyle": "custom" + } + }, + { + "path": "pages/sales/invoicingRegistration/view", + "style": { + "navigationBarTitleText": "寮�绁ㄧ櫥璁拌鎯�", + "navigationStyle": "custom" + } + }, + { "path": "pages/common/webview/index", "style": { "navigationBarTitleText": "娴忚缃戦〉" @@ -82,7 +103,6 @@ "navigationBarTitleText": "娴忚鏂囨湰" } }, - //鍗忓悓瀹℃壒 { "path": "pages/cooperativeOffice/collaborativeApproval/index", "style": { @@ -97,7 +117,6 @@ "navigationStyle": "custom" } }, - //瀹㈡埛鎷滆 { "path": "pages/cooperativeOffice/clientVisit/index", "style": { diff --git a/src/pages/index.vue b/src/pages/index.vue index ff3036b..1b9f36e 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -293,6 +293,11 @@ url: '/pages/sales/salesAccount/index' }); break; + case '寮�绁ㄧ櫥璁�': + uni.navigateTo({ + url: '/pages/sales/invoicingRegistration/index' + }); + break; case '鍗忓悓瀹℃壒': uni.navigateTo({ url: '/pages/cooperativeOffice/collaborativeApproval/index' 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> diff --git a/src/pages/sales/invoicingRegistration/index.vue b/src/pages/sales/invoicingRegistration/index.vue new file mode 100644 index 0000000..e3faef5 --- /dev/null +++ b/src/pages/sales/invoicingRegistration/index.vue @@ -0,0 +1,448 @@ +<template> + <view class="sales-account"> + <!-- 椤甸潰澶撮儴 --> + <van-nav-bar + title="寮�绁ㄧ櫥璁�" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> + + <!-- 鎼滅储鍜岀瓫閫夊尯鍩� --> + <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="total > 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.salesContractNo }}</text> + </view> + <!-- <view class="item-tag">--> + <!-- <text class="tag-text">{{ item.recorder }}</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.customerName }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">瀹㈡埛鍚堝悓鍙�</text> + <text class="detail-value">{{ item.customerContractNo }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">涓氬姟鍛�</text> + <text class="detail-value">{{ item.salesman }}</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.invoiceTotal }}</text> + </view> + <view class="detail-row"> + <text class="detail-label">鏈紑绁ㄩ噾棰�(鍏�)</text> + <text class="detail-value redlight">{{ item.noInvoiceAmountTotal }}</text> + </view> + </view> + + <!-- 鎿嶄綔鎸夐挳鍖哄煙 --> + <view class="action-buttons"> + <van-button + type="primary" + size="small" + @click="handleAddInvoice(item)" + class="action-btn" + :disabled="item.entryPerson != userStore.id || item.noInvoiceAmountTotal == 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 class="fab-button" @click="handleInfo('add')"> + <up-icon name="plus" size="24" color="#ffffff"></up-icon> + </view> --> + </view> +</template> + +<script setup> +import { ref } from 'vue'; +import { onShow } from '@dcloudio/uni-app'; +import {ledgerListPage} from "@/api/salesManagement/salesLedger"; +import useUserStore from "@/store/modules/user"; +const userStore = useUserStore() + +// 鎼滅储鍏抽敭璇� +const searchKeyword = ref(''); + +// 閿�鍞彴璐︽暟鎹� +const ledgerList = ref([]); +const total = ref(0); + +// 鍚堝悓閫夋嫨鍣ㄧ浉鍏� +const contractList = ref([]); +const contractLoading = ref(false); +const contractFinished = ref(false); + +// 杩斿洖涓婁竴椤� +const goBack = () => { + uni.navigateBack(); +}; +// 鏌ヨ鍒楄〃 +const getList = () => { + const page = { + current: -1, + size: -1 + } + ledgerListPage({...page}).then((res) => { + ledgerList.value = res.records; + total.value = res.total; + }).catch(() => { + // tableLoading.value = false; + }); +}; + +// 澶勭悊鏂板寮�绁� +const handleAddInvoice = (item) => { + try { + // 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳芥柊澧炲紑绁� + if (item.entryPerson != userStore.id) { + uni.showToast({ + title: '鍙湁褰曞叆浜烘墠鑳芥柊澧炲紑绁�', + icon: 'none' + }); + return; + } + + // 瀛樺偍閫変腑鐨勫悎鍚屼俊鎭� + uni.setStorageSync('editData', JSON.stringify(item)); + + // 璺宠浆鍒版柊澧炲紑绁ㄩ〉闈� + uni.navigateTo({ + url: '/pages/sales/invoicingRegistration/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/sales/invoicingRegistration/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; + text-align: center; +} + +.page-title { + font-size: 18px; + font-weight: 600; + color: #333; +} + +.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/sales/invoicingRegistration/view.vue b/src/pages/sales/invoicingRegistration/view.vue new file mode 100644 index 0000000..2050719 --- /dev/null +++ b/src/pages/sales/invoicingRegistration/view.vue @@ -0,0 +1,325 @@ +<template> + <view class="account-view"> + <!-- 椤堕儴鏍囬鏍� --> + <van-nav-bar + title="寮�绁ㄧ櫥璁拌鎯�" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> + + <!-- 鍩烘湰淇℃伅灞曠ず --> + <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.salesContractNo }}</text> + </view> + <view class="info-item"> + <text class="info-label">瀹㈡埛鍚堝悓鍙�</text> + <text class="info-value">{{ form.customerContractNo }}</text> + </view> + <view class="info-item"> + <text class="info-label">瀹㈡埛鍚嶇О</text> + <text class="info-value">{{ form.customerName }}</text> + </view> + <view class="info-item"> + <text class="info-label">涓氬姟鍛�</text> + <text class="info-value">{{ form.salesman }}</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.invoiceTotal }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈紑绁ㄩ噾棰�(鍏�)</text> + <text class="info-value redlight">{{ form.noInvoiceAmountTotal }}</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.invoiceNum }}</text> + </view> + <view class="info-item"> + <text class="info-label">寮�绁ㄩ噾棰�(鍏�)</text> + <text class="info-value highlight">{{ product.invoiceAmount }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈紑绁ㄦ暟</text> + <text class="info-value highlight">{{ product.noInvoiceNum }}</text> + </view> + <view class="info-item"> + <text class="info-label">鏈紑绁ㄩ噾棰�(鍏�)</text> + <text class="info-value redlight">{{ product.noInvoiceAmount }}</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 { getSalesLedgerWithProducts } from "@/api/salesManagement/salesLedger"; + +// 琛ㄥ崟鏁版嵁 +const form = ref({ + id: '', + salesContractNo: '', + customerContractNo: '', + customerId: '', + customerName: '', + projectName: '', + executionDate: '', + contractAmount: '', + invoiceTotal: '', + noInvoiceAmountTotal: '', + salesman: '' +}); + +// 浜у搧鏁版嵁 +const productData = ref([]); + +// 缂栬緫鏁版嵁 +const editData = ref(null); + +// 杩斿洖涓婁竴椤� +const goBack = () => { + // 娓呯悊鏈湴瀛樺偍鐨勬暟鎹� + uni.removeStorageSync('editData'); + uni.navigateBack(); +}; + +// 濉厖琛ㄥ崟鏁版嵁 +const fillFormData = () => { + if (!editData.value) return; + + // 鑾峰彇瀹屾暣鐨勪骇鍝佷俊鎭� + getSalesLedgerWithProducts({ id: editData.value.id, type: 1 }).then((res) => { + productData.value = res.productData || []; + }); + + // 濉厖鍩烘湰淇℃伅 + form.value.salesContractNo = editData.value.salesContractNo || ''; + form.value.customerContractNo = editData.value.customerContractNo || ''; + form.value.customerName = editData.value.customerName || ''; + form.value.projectName = editData.value.projectName || ''; + form.value.executionDate = editData.value.executionDate || ''; + form.value.contractAmount = editData.value.contractAmount || ''; + form.value.salesman = editData.value.salesman || ''; + form.value.invoiceTotal = editData.value.invoiceTotal || 0; + form.value.noInvoiceAmountTotal = editData.value.noInvoiceAmountTotal || 0; + form.value.id = editData.value.id || ''; + form.value.customerId = editData.value.customerId || ''; +}; + +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/salesAccount/detail.vue b/src/pages/sales/salesAccount/detail.vue index d5b2522..c243a88 100644 --- a/src/pages/sales/salesAccount/detail.vue +++ b/src/pages/sales/salesAccount/detail.vue @@ -1,10 +1,14 @@ <template> <view class="account-detail"> <!-- 椤堕儴鏍囬鏍� --> - <view class="header"> - <up-icon name="arrow-left" size="20" color="#333" @click="goBack" /> - <text class="title">鍙拌处璇︽儏</text> - </view> + <van-nav-bar + title="鍙拌处璇︽儏" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> <!-- 琛ㄥ崟鍖哄煙 --> <van-form @submit="onSubmit" label-width="110px" input-align="right" style="margin-top: 10px" error-message-align="right" scroll-to-error scroll-to-error-position="center"> diff --git a/src/pages/sales/salesAccount/index.vue b/src/pages/sales/salesAccount/index.vue index 336e593..e4756ed 100644 --- a/src/pages/sales/salesAccount/index.vue +++ b/src/pages/sales/salesAccount/index.vue @@ -1,14 +1,14 @@ <template> <view class="sales-account"> <!-- 椤甸潰澶撮儴 --> - <view class="page-header"> - <view class="header-left"> - <up-icon name="arrow-left" size="20" color="#333" @click="goBack"></up-icon> - </view> - <view class="header-center"> - <text class="page-title">閿�鍞彴璐�</text> - </view> - </view> + <van-nav-bar + title="閿�鍞彴璐�" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> <!-- 鎼滅储鍜岀瓫閫夊尯鍩� --> <view class="search-filter-section"> @@ -50,7 +50,7 @@ </view> <view class="detail-row"> <text class="detail-label">瀹㈡埛鍚堝悓鍙�</text> - <text class="detail-value highlight">{{ item.customerContractNo }}</text> + <text class="detail-value">{{ item.customerContractNo }}</text> </view> <view class="detail-row"> <text class="detail-label">涓氬姟鍛�</text> @@ -148,7 +148,7 @@ } // 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳界紪杈� - if (row.entryPerson !== userStore.id) { + if (row.entryPerson != userStore.id) { // 闈炲綍鍏ヤ汉璺宠浆鍒板彧璇昏鎯呴〉闈� uni.setStorageSync('editData', JSON.stringify(row)); uni.navigateTo({ diff --git a/src/pages/sales/salesAccount/view.vue b/src/pages/sales/salesAccount/view.vue index 99a76b2..1076379 100644 --- a/src/pages/sales/salesAccount/view.vue +++ b/src/pages/sales/salesAccount/view.vue @@ -1,10 +1,14 @@ <template> <view class="account-view"> <!-- 椤堕儴鏍囬鏍� --> - <view class="header"> - <up-icon name="arrow-left" size="20" color="#333" @click="goBack" /> - <text class="title">鍙拌处璇︽儏</text> - </view> + <van-nav-bar + title="鍙拌处璇︽儏" + left-text="杩斿洖" + left-arrow + @click-left="goBack" + fixed + placeholder + /> <!-- 鍩烘湰淇℃伅灞曠ず --> <view class="info-section"> -- Gitblit v1.9.3