src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/invoiceLedger/detail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/invoiceLedger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/invoicingRegistration/add.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/receiptPayment/add.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/receiptPayment/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/salesAccount/detail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/pages.json
@@ -106,6 +106,20 @@ } }, { "path": "pages/sales/receiptPayment/index", "style": { "navigationBarTitleText": "忬¾ç»è®°", "navigationStyle": "custom" } }, { "path": "pages/sales/receiptPayment/add", "style": { "navigationBarTitleText": "æ°å¢å款", "navigationStyle": "custom" } }, { "path": "pages/common/webview/index", "style": { "navigationBarTitleText": "æµè§ç½é¡µ" src/pages/index.vue
@@ -303,6 +303,11 @@ url: '/pages/sales/invoiceLedger/index' }); break; case '忬¾ç»è®°': uni.navigateTo({ url: '/pages/sales/receiptPayment/index' }); break; case 'åå审æ¹': uni.navigateTo({ url: '/pages/cooperativeOffice/collaborativeApproval/index' src/pages/sales/invoiceLedger/detail.vue
@@ -87,6 +87,7 @@ const currentInvoiceDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) const goBack = () => { uni.removeStorageSync('invoiceLedgerEditRow'); uni.navigateBack() } src/pages/sales/invoiceLedger/index.vue
@@ -230,6 +230,7 @@ commitFile, delInvoiceLedgerByRegProductId } from '@/api/salesManagement/invoiceLedger.js' import {onShow} from "@dcloudio/uni-app"; const userStore = useUserStore() @@ -518,7 +519,7 @@ } } onMounted(() => { onShow(() => { getList() }) </script> src/pages/sales/invoicingRegistration/add.vue
@@ -358,7 +358,7 @@ productData.value = res.productData; form.value = { ...res }; // 设置é»è®¤å½å ¥äºº form.value.createUer = userStore.name || '' form.value.createUer = userStore.nickName || '' // 设置é»è®¤æ¥æ const today = new Date() src/pages/sales/receiptPayment/add.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,299 @@ <template> <view class="account-detail"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="æ°å¢å款" left-text="è¿å" left-arrow @click-left="onClickLeft" fixed placeholder /> <!-- 表åå 容 --> <van-form @submit="onSubmit" 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="éå®ååå·" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.customerName" label="客æ·åç§°" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.invoiceNo" label="å票å·" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.invoiceTotal" label="å票éé¢(å )" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.taxRate" label="ç¨ç" placeholder="èªå¨å¡«å " readonly /> <view class="tip-text">å¾ åæ¬¾éé¢ï¼{{ currentNoReceiptAmount }} å </view> <van-field v-model="form.receiptPaymentAmount" label="æ¬æ¬¡å款éé¢" type="number" placeholder="请è¾å ¥" @blur="changeNum" :rules="[{ required: true, message: '请è¾å ¥å款éé¢' }]" clearable /> <van-field v-model="form.receiptPaymentTypeName" label="忬¾å½¢å¼" placeholder="è¯·éæ©" readonly @click="showPaymentTypePicker" :rules="[{ required: true, message: 'è¯·éæ©åæ¬¾å½¢å¼' }]" /> <van-field v-model="form.receiptPaymentDate" label="æ¥æ¬¾æ¥æ" placeholder="è¯·éæ©" readonly @click="showDatePicker" :rules="[{ required: true, message: 'è¯·éæ©æ¥æ¬¾æ¥æ' }]" /> <van-field v-model="form.registrant" label="ç»è®°äºº" placeholder="èªå¨å¡«å " readonly /> </van-cell-group> <!-- æäº¤æé® --> <view class="footer-btns"> <van-button class="cancel-btn" @click="onClickLeft">åæ¶</van-button> <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> </view> </van-form> <!-- 忬¾æ¹å¼éæ©å¨ --> <van-popup v-model:show="showPaymentType" position="bottom"> <van-picker :model-value="pickerValue" :columns="receipt_payment_type" @confirm="onPaymentTypeConfirm" @cancel="showPaymentType = false" /> </van-popup> <!-- æ¥æéæ©å¨ --> <van-popup v-model:show="showDate" position="bottom"> <van-date-picker v-model="currentDate" title="éæ©æ¥æ" @confirm="onDateConfirm" @cancel="showDate = false" /> </van-popup> </view> </template> <script setup> import { ref, onMounted, computed } from 'vue' import { receiptPaymentSaveOrUpdate, invoiceInfo } from '@/api/salesManagement/receiptPayment' import useUserStore from '@/store/modules/user' import { showToast, showNotify } from 'vant' import { useDict } from '@/utils/dict' const userStore = useUserStore() // 表åå¼ç¨ const formRef = ref() // ååºå¼æ°æ® const loading = ref(false) const showPaymentType = ref(false) const pickerValue = ref([]) const showDate = ref(false) const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) // è¡¨åæ°æ® const form = ref({ salesContractNo: '', customerName: '', invoiceNo: '', invoiceTotal: '', taxRate: '', receiptPaymentAmount: '', receiptPaymentType: '', receiptPaymentTypeName: '', registrant: '', receiptPaymentDate: '', invoiceLedgerId: '' }) const currentNoReceiptAmount = ref(0) // è·ååå ¸æ°æ® const { receipt_payment_type: dictReceiptPaymentType } = useDict('receipt_payment_type') // 转æ¢åå ¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ const receipt_payment_type = computed(() => { return dictReceiptPaymentType.value.map(item => ({ text: item.label, value: item.value })) }) // è¿åä¸ä¸é¡µ const onClickLeft = () => { uni.removeStorageSync('invoiceLedgerEditRow'); uni.navigateBack() } // æ¾ç¤ºå款æ¹å¼éæ©å¨ const showPaymentTypePicker = () => { showPaymentType.value = true } const changeNum = () => { if (form.value.receiptPaymentAmount > currentNoReceiptAmount.value) { form.value.receiptPaymentAmount = currentNoReceiptAmount.value showToast('ä¸å¯å¤§äºå¾ 忬¾éé¢') } } // ç¡®è®¤åæ¬¾æ¹å¼éæ© const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { form.value.receiptPaymentType = selectedOptions[0].value form.value.receiptPaymentTypeName = selectedOptions[0].text pickerValue.value = selectedValues; showPaymentType.value = false } // æ¾ç¤ºæ¥æéæ©å¨ const showDatePicker = () => { showDate.value = true } // ç¡®è®¤æ¥æéæ© const onDateConfirm = ({ selectedValues }) => { form.value.receiptPaymentDate = selectedValues.join('-') currentDate.value = selectedValues showDate.value = false } // æäº¤è¡¨å const onSubmit = () => { // 表åéªè¯ if (!form.value.receiptPaymentAmount) { showNotify({ type: 'warning', message: '请è¾å ¥å款éé¢' }) return } if (!form.value.receiptPaymentType) { showNotify({ type: 'warning', message: 'è¯·éæ©åæ¬¾å½¢å¼' }) return } if (!form.value.receiptPaymentDate) { showNotify({ type: 'warning', message: 'è¯·éæ©æ¥æ¬¾æ¥æ' }) return } loading.value = true receiptPaymentSaveOrUpdate(form.value) .then(() => { showToast('æäº¤æå') // éç¥ä¸ä¸é¡µå·æ°æ°æ® const pages = getCurrentPages(); const prevPage = pages[pages.length - 2]; if (prevPage && prevPage.$vm && prevPage.$vm.getList) { prevPage.$vm.getList(); } uni.removeStorageSync('invoiceLedgerEditRow'); uni.navigateBack() }) .catch((error) => { loading.value = false }) } // åå§åæ°æ® const initData = () => { const rowStr = uni.getStorageSync('invoiceLedgerEditRow') const row = JSON.parse(rowStr) invoiceInfo({ id: row.id }).then((res) => { const data = res.data form.value = { ...data} form.value.invoiceLedgerId = form.value.id; form.value.id = ""; currentNoReceiptAmount.value = row.noReceiptAmount form.value.registrant = userStore.nickName }).catch(() => { showToast('è·åæ°æ®å¤±è´¥') }) } onMounted(() => { initData() }) </script> <style scoped lang="scss"> .account-detail { min-height: 100vh; background: #f8f9fa; padding-bottom: 5rem; } .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; } } .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } </style> src/pages/sales/receiptPayment/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,405 @@ <template> <view class="receipt-payment"> <!-- 页é¢å¤´é¨ --> <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="searchForm.searchText" confirm-type="search" /> </view> <view class="filter-button" @click="getList"> <up-icon name="search" size="24" color="#999"></up-icon> </view> </view> <!-- çéå¼å ³ --> <view class="switch-row"> <text class="switch-label">䏿¾ç¤ºå¾ 忬¾ä¸º0</text> <van-switch v-model="searchForm.status" @change="getList" size="18"/> </view> </view> <!-- å表åºå --> <view class="ledger-list" v-if="tableData.length > 0"> <view v-for="(item, index) in tableData" :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> <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.projectName }}</text> </view> <view class="detail-row"> <text class="detail-label">产å大类</text> <text class="detail-value">{{ item.productCategory }}</text> </view> <view class="detail-row"> <text class="detail-label">å票å·</text> <text class="detail-value">{{ item.invoiceNo || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">å票éé¢(å )</text> <text class="detail-value highlight">{{ formatNumber(item.invoiceTotal) }}</text> </view> <view class="detail-row"> <text class="detail-label">ç¨ç(%)</text> <text class="detail-value">{{ item.taxRate }}</text> </view> <view class="detail-row"> <text class="detail-label">忬¾éé¢(å )</text> <text class="detail-value highlight">{{ formatNumber(item.receiptPaymentAmountTotal) }}</text> </view> <view class="detail-row"> <text class="detail-label">å¾ åæ¬¾éé¢(å )</text> <text class="detail-value danger">{{ formatNumber(item.noReceiptAmount) }}</text> </view> </view> <!-- æä½æé® --> <view class="action-buttons"> <van-button type="primary" size="small" class="action-btn" :disabled="item.noReceiptAmount == 0" @click="openForm(item)" > æ°å¢å款 </van-button> </view> </view> </view> </view> <!-- æ æ°æ®æç¤º --> <view class="no-data" v-else> <text>ææ åæ¬¾æ°æ®</text> </view> <!-- 忬¾æ¹å¼éæ©å¨ --> <van-popup v-model:show="showPaymentType" position="bottom"> <van-picker :columns="receipt_payment_type" @confirm="onPaymentTypeConfirm" @cancel="showPaymentType = false" /> </van-popup> </view> </template> <script setup> import { ref } from 'vue' import { bindInvoiceNoRegPage, } from '@/api/salesManagement/receiptPayment' import useUserStore from '@/store/modules/user' import { showToast } from 'vant' import {onShow} from "@dcloudio/uni-app"; const userStore = useUserStore() // ååºå¼æ°æ® const tableData = ref([]) const tableLoading = ref(false) const showPaymentType = ref(false) const currentEditRow = ref(null) // æ¥è¯¢åæ°è®¾ç½®ä¸º-1è·åå ¨é¨æ°æ® const page = ref({ current: -1, size: -1 }) // æç´¢è¡¨å const searchForm = ref({ searchText: '', status: true, customerName: '', customerContractNo: '', projectName: '' }) // 忬¾æ¹å¼é项 const receipt_payment_type = ref([ { text: 'ç°é', value: '1' }, { text: 'é¶è¡è½¬è´¦', value: '2' }, { text: 'æ¯ç¥¨', value: '3' }, { text: 'å ¶ä»', value: '4' } ]) // æ ¼å¼åæ°å const formatNumber = (value) => { return parseFloat(value || 0).toFixed(2) } // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack() } // è·ååè¡¨æ°æ® const getList = () => { tableLoading.value = true bindInvoiceNoRegPage({ ...searchForm.value, ...page.value }) .then((res) => { tableLoading.value = false tableData.value = res.data.records || [] }) .catch(() => { tableLoading.value = false }) } // æå¼æ°å¢è¡¨å const openForm = (item) => { if (item.noReceiptAmount == 0) { showToast('æ éå忬¾') return } uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) uni.navigateTo({ url: '/pages/sales/receiptPayment/add' }) } // ç¡®è®¤åæ¬¾æ¹å¼éæ© const onPaymentTypeConfirm = (value) => { if (currentEditRow.value) { currentEditRow.value.receiptPaymentType = value.value } showPaymentType.value = false } onShow(() => { getList() }) </script> <style scoped lang="scss"> .u-divider { margin: 0 !important; } .receipt-payment { min-height: 100vh; background: #f8f9fa; position: relative; } .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; } .switch-row { padding: 8px; display: flex; align-items: center; justify-content: space-between; margin-top: 8px; } .switch-label { font-size: 14px; color: #333; } .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-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-label { font-size: 12px; color: #777777; min-width: 60px; } .detail-value { font-size: 12px; color: #000000; text-align: right; flex: 1; margin-left: 16px; display: flex; align-items: center; justify-content: flex-end; } .detail-value.highlight { color: #2979ff; font-weight: 500; } .detail-value.danger { color: #ee0a24; font-weight: 500; } .children-list { .children-title { font-size: 14px; font-weight: 500; color: #333; padding: 12px 0 8px 0; border-top: 1px solid #f0f0f0; } } .child-item { .child-details { padding: 12px 0; } .child-actions { display: flex; gap: 8px; padding: 8px 0 16px 0; justify-content: flex-end; } } .action-buttons { display: flex; gap: 12px; padding: 0 0 16px 0; justify-content: space-between; } .action-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; } .no-data { padding: 40px 0; text-align: center; color: #999; } </style> src/pages/sales/salesAccount/detail.vue
@@ -616,7 +616,7 @@ }; const setUserInfo = () => { form.value.entryPerson = userStore.id; form.value.entryPersonName = userStore.name; form.value.entryPersonName = userStore.nickName; // 设置å½å¤©æ¥æ const today = new Date() const year = today.getFullYear()