src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/paymentEntry/add.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/paymentEntry/edit.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/paymentEntry/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/receiptPaymentHistory/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/pages.json
@@ -212,6 +212,20 @@ } }, { "path": "pages/procurementManagement/paymentEntry/edit", "style": { "navigationBarTitleText": "ä¿®æ¹ä»æ¬¾ç»è®°", "navigationStyle": "custom" } }, { "path": "pages/procurementManagement/receiptPaymentHistory/index", "style": { "navigationBarTitleText": "仿¬¾æµæ°´", "navigationStyle": "custom" } }, { "path": "pages/common/webview/index", "style": { "navigationBarTitleText": "æµè§ç½é¡µ" src/pages/index.vue
@@ -342,7 +342,7 @@ break; case '仿¬¾æµæ°´': uni.navigateTo({ url: '/pages/procurementManagement/paymentEntry/index' url: '/pages/procurementManagement/receiptPaymentHistory/index' }); break; case 'åå审æ¹': src/pages/procurementManagement/paymentEntry/add.vue
@@ -109,7 +109,6 @@ <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' src/pages/procurementManagement/paymentEntry/edit.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,280 @@ <template> <view class="account-detail"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="æ°å¢ä»æ¬¾" @back="onClickLeft" /> <!-- 表åå 容 --> <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.purchaseContractNumber" label="éè´ååå·" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.supplierName" label="ä¾åºååç§°" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.invoiceNumber" label="å票å·" placeholder="èªå¨å¡«å " readonly /> <van-field v-model="form.invoiceAmount" label="å票éé¢(å )" placeholder="èªå¨å¡«å " readonly /> <view class="tip-text">å¾ ä»æ¬¾éé¢ï¼{{ currentNoReceiptAmount }} å </view> <van-field v-model="form.currentPaymentAmount" label="æ¬æ¬¡ä»æ¬¾éé¢" type="number" placeholder="请è¾å ¥" @blur="changeNum" :rules="[{ required: true, message: '请è¾å ¥ä»æ¬¾éé¢' }]" clearable /> <van-field v-model="form.paymentMethod" label="仿¬¾å½¢å¼" placeholder="è¯·éæ©" readonly @click="showPaymentTypePicker" :rules="[{ required: true, message: 'è¯·éæ©ä»æ¬¾å½¢å¼' }]" /> <van-field v-model="form.paymentDate" label="仿¬¾æ¥æ" placeholder="è¯·éæ©" readonly @click="showDatePicker" :rules="[{ required: true, message: 'è¯·éæ©æ¥æ¬¾æ¥æ' }]" /> </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' import {paymentRegistrationAdd, paymentRegistrationEdit} from "@/api/procurementManagement/paymentEntry"; 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({ purchaseContractNumber: '', salesContractNo: '', supplierName: '', invoiceNumber: '', invoiceAmount: '', taxRate: '', currentPaymentAmount: '', receiptPaymentType: '', paymentMethod: '', registrant: '', paymentDate: '', registrationtDate: '', ticketRegistrationId: '' }) const currentNoReceiptAmount = ref(0) const operationType = ref('') // è·ååå ¸æ°æ® 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.currentPaymentAmount > currentNoReceiptAmount.value) { form.value.currentPaymentAmount = currentNoReceiptAmount.value showToast('ä¸å¯å¤§äºå¾ 仿¬¾éé¢') } } // ç¡®è®¤ä»æ¬¾æ¹å¼éæ© const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { form.value.receiptPaymentType = selectedOptions[0].value form.value.paymentMethod = selectedOptions[0].text pickerValue.value = selectedValues; showPaymentType.value = false } // æ¾ç¤ºæ¥æéæ©å¨ const showDatePicker = () => { showDate.value = true } // ç¡®è®¤æ¥æéæ© const onDateConfirm = ({ selectedValues }) => { form.value.paymentDate = selectedValues.join('-') currentDate.value = selectedValues showDate.value = false } // æäº¤è¡¨å const onSubmit = () => { // 表åéªè¯ if (!form.value.currentPaymentAmount) { showNotify({ type: 'warning', message: '请è¾å ¥ä»æ¬¾éé¢' }) return } if (!form.value.receiptPaymentType) { showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾å½¢å¼' }) return } if (!form.value.paymentDate) { showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾æ¥æ' }) return } loading.value = true paymentRegistrationEdit(form.value) .then(() => { showToast('æäº¤æå') onClickLeft() }) .catch((error) => { loading.value = false }) } // åå§åæ°æ® const initData = () => { const rowStr = uni.getStorageSync('invoiceLedgerEditRow') const row = JSON.parse(rowStr) form.value = { ...row }; form.value.ticketRegistrationId = row.id; form.value.id = ""; if (operationType.value === 'add') { currentNoReceiptAmount.value = row.unPaymentAmountTotal form.value.registrant = userStore.nickName form.value.registrationtDate = getCurrentDate(); form.value.paymentDate = getCurrentDate(); } } // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD function getCurrentDate() { const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ const day = String(today.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; } onMounted(() => { operationType.value = uni.getStorageSync('operationType') || ''; 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/procurementManagement/paymentEntry/index.vue
@@ -75,7 +75,7 @@ size="small" class="action-btn" :disabled="item.unPaymentAmountTotal == 0" @click="openForm(item)" @click="openForm('add', item)" > æ°å¢ä»æ¬¾ </van-button> @@ -139,11 +139,12 @@ } // æå¼æ°å¢è¡¨å const openForm = (item) => { const openForm = (type, item) => { if (item.unPaymentAmountTotal == 0) { showToast('æ éå仿¬¾') return } uni.setStorageSync('operationType', type); uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) uni.navigateTo({ url: '/pages/procurementManagement/paymentEntry/add' }) } src/pages/procurementManagement/receiptPaymentHistory/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,381 @@ <template> <view class="receipt-payment-history"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="仿¬¾æµæ°´" @back="goBack" /> <!-- æç´¢åºå --> <view class="search-section"> <view class="search-bar"> <view class="search-input"> <input class="search-text" placeholder="请è¾å ¥ä¾åºååç§°" v-model="searchForm.searchText" @input="getList" /> </view> <view class="search-button" @click="getList"> <up-icon name="search" size="24" color="#999"></up-icon> </view> </view> </view> <!-- ç»è®¡ä¿¡æ¯ --> <view class="summary-info" v-if="tableData.length > 0"> <view class="summary-item"> <text class="summary-label">æ»è®°å½æ°</text> <text class="summary-value">{{ tableData.length }}</text> </view> <view class="summary-item"> <text class="summary-label">æ»éé¢</text> <text class="summary-value highlight">{{ formatAmount(totalAmount) }}</text> </view> </view> <!-- 仿¬¾åå²å表 --> <view class="history-list" v-if="tableData.length > 0"> <view v-for="(item, index) in tableData" :key="index"> <view class="history-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 class="item-tag" :class="getTagClass(item.paymentMethod)"> <text class="tag-text">{{ item.paymentMethod }}</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.supplierName }}</text> </view> <view class="detail-row"> <text class="detail-label">仿¬¾éé¢(å )</text> <text class="detail-value highlight">{{ formatAmount(item.currentPaymentAmount) }}</text> </view> <view class="detail-row"> <text class="detail-label">仿¬¾æ¥æ</text> <text class="detail-value">{{ item.paymentDate }}</text> </view> <up-divider></up-divider> <view class="detail-info"> <view class="detail-row"> <text class="detail-label">ç»è®°äºº</text> <text class="detail-value">{{ item.registrant }}</text> </view> <view class="detail-row"> <text class="detail-label">ç»è®°æ¥æ</text> <text class="detail-value">{{ item.registrationtDate }}</text> </view> </view> <!-- æä½æé® --> <view class="action-buttons"> <van-button type="primary" size="small" class="action-btn" @click="openForm(item)" > ç¼è¾ä»æ¬¾ </van-button> </view> </view> </view> </view> </view> <view v-else class="no-data"> <text>ææ ä»æ¬¾å岿°æ®</text> </view> </view> </template> <script setup> import { ref, computed } from 'vue'; import { onShow } from '@dcloudio/uni-app'; import {paymentHistoryListPage} from "@/api/procurementManagement/paymentEntry"; // æç´¢è¡¨å const searchForm = ref({ searchText: '', }); // è¡¨æ ¼æ°æ® const tableData = ref([]); // å页忰 const page = ref({ current: -1, size: -1, }); const totalAmount = computed(() => { return tableData.value.reduce((sum, item) => { return sum + (parseFloat(item.receiptPaymentAmount) || 0); }, 0); }); // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack(); }; // æ¥è¯¢å表 const getList = () => { const params = { ...searchForm.value, ...page.value }; paymentHistoryListPage(params).then((res) => { tableData.value = res.records; }).catch(() => { uni.showToast({ title: 'æ¥è¯¢å¤±è´¥', icon: 'error' }); }); }; // è·åæ ç¾æ ·å¼ç±» const getTagClass = (type) => { if (type == 'çµæ±') { return "tag-electric"; } else if (type == 'æ¿å ') { return "tag-acceptance"; } else { return "tag-unknown"; } }; // æ ¼å¼åéé¢ const formatAmount = (amount) => { return amount ? parseFloat(amount).toFixed(2) : '0.00'; }; // æå¼ç¼è¾è¡¨å const openForm = (item) => { uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) uni.navigateTo({ url: '/pages/procurementManagement/paymentEntry/edit' }) } onShow(() => { // 页颿¾ç¤ºæ¶å·æ°å表 getList(); }); </script> <style scoped lang="scss"> .u-divider { margin: 0 !important; } .receipt-payment-history { min-height: 100vh; background: #f8f9fa; position: relative; } .search-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; } .search-button { width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; } .history-list { padding: 20px; } .history-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 { border-radius: 4px; padding: 2px 8px; } .tag-electric { background: #4caf50; } .tag-acceptance { background: #ff9800; } .tag-unknown { background: #9e9e9e; } .tag-text { font-size: 14px; 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; } .action-buttons { display: flex; gap: 12px; padding: 12px 0 0 0; justify-content: space-between; } .action-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; } .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; } .no-data { padding: 40px 0; text-align: center; color: #999; } .summary-info { background: #ffffff; margin: 20px 20px 0 20px; border-radius: 12px; padding: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } .summary-item { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; &:last-child { margin-bottom: 0; } } .summary-label { font-size: 14px; color: #666; } .summary-value { font-size: 14px; color: #333; font-weight: 500; } .summary-value.highlight { color: #2979ff; font-weight: 600; } </style>