src/components/PageHeader.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/invoiceEntry/add.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/invoiceEntry/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/procurementManagement/invoiceEntry/view.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/sales/invoicingRegistration/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/components/PageHeader.vue
@@ -48,7 +48,7 @@ props.customBack(); } else { emit('back'); uni.navigateBack(); // uni.navigateBack(); } }; </script> 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": "æµè§ç½é¡µ" 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' 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> 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> 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('è§£æç¼è¾æ°æ®å¤±è´¥:', 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> 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> @@ -74,7 +71,7 @@ size="small" @click="handleAddInvoice(item)" class="action-btn" :disabled="item.entryPerson != userStore.id || item.noInvoiceAmountTotal == 0" :disabled="item.noInvoiceAmountTotal == 0" > æ°å¢å¼ç¥¨ </van-button> @@ -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));