src/components/PageHeader.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,103 @@ <template> <view class="page-header"> <view class="header-left"> <up-icon name="arrow-left" size="20" color="#333" @click="handleBack" ></up-icon> </view> <view class="header-center"> <text class="page-title">{{ title }}</text> </view> <view class="header-right" v-if="$slots.right"> <slot name="right"></slot> </view> </view> </template> <script setup> import { defineProps, defineEmits } from 'vue'; // å®ä¹ç»ä»¶å±æ§ const props = defineProps({ // 页颿 é¢ title: { type: String, default: '' }, // æ¯å¦æ¾ç¤ºè¿åæé® showBack: { type: Boolean, default: true }, // èªå®ä¹è¿åäºä»¶ customBack: { type: Function, default: null } }); // å®ä¹äºä»¶ const emit = defineEmits(['back']); // å¤çè¿åäºä»¶ const handleBack = () => { if (props.customBack) { props.customBack(); } else { emit('back'); uni.navigateBack(); } }; </script> <style scoped lang="scss"> .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: calc(env(safe-area-inset-top)); top: 0; z-index: 100; position: relative; } .header-left { display: flex; align-items: center; gap: 8px; min-width: 30px; /* ç¡®ä¿ç¹å»åºåè¶³å¤å¤§ */ } .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; min-width: 44px; /* ç¡®ä¿å³ä¾§åºåæè¶³å¤ç©ºé´ */ justify-content: flex-end; } </style> src/components/index.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ // å ¨å±ç»ä»¶æ³¨å import PageHeader from './PageHeader.vue' // ç»ä»¶å表 const components = [ { name: 'PageHeader', component: PageHeader } ] // å®è£ 彿° export function setupGlobalComponents(app) { components.forEach(({ name, component }) => { app.component(name, component) }) } // 导åºç»ä»¶ export { PageHeader } src/main.js
@@ -4,6 +4,7 @@ import uviewPlus from 'uview-plus' import Vant from 'vant'; import 'vant/lib/index.css'; import { setupGlobalComponents } from './components' import { createSSRApp } from 'vue' @@ -23,6 +24,9 @@ app.use(uviewPlus) app.use(plugins) app.use(Vant) // 注åå ¨å±ç»ä»¶ setupGlobalComponents(app) // #ifndef MP-WEIXIN // 微信å°ç¨åºä¸ä¸æ¯æèªå®ä¹æä»¤ src/pages.json
@@ -94,7 +94,7 @@ { "path": "pages/sales/invoiceLedger/index", "style": { "navigationBarTitleText": "å¼ç¥¨å°è´¦", "navigationBarTitleText": "", "navigationStyle": "custom" } }, @@ -120,6 +120,27 @@ } }, { "path": "pages/sales/receiptPaymentHistory/index", "style": { "navigationBarTitleText": "忬¾æµæ°´", "navigationStyle": "custom" } }, { "path": "pages/sales/receiptPaymentLedger/index", "style": { "navigationBarTitleText": "客æ·å¾æ¥", "navigationStyle": "custom" } }, { "path": "pages/sales/receiptPaymentLedger/detail", "style": { "navigationBarTitleText": "客æ·å¾æ¥è¯¦æ ", "navigationStyle": "custom" } }, { "path": "pages/common/webview/index", "style": { "navigationBarTitleText": "æµè§ç½é¡µ" src/pages/cooperativeOffice/clientVisit/index.vue
@@ -34,6 +34,7 @@ justify-content: space-between; padding: 10px 20px; background-color: #f5f5f5; position: relative; } .header-left { display: flex; @@ -41,11 +42,18 @@ } .header-center { flex: 1; text-align: center; display: flex; justify-content: center; align-items: center; position: absolute; left: 0; right: 0; pointer-events: none; } .page-title { font-size: 18px; font-weight: bold; pointer-events: auto; } </style> src/pages/cooperativeOffice/collaborativeApproval/index.vue
@@ -1,15 +1,8 @@ // 审æ¹ç®¡çä¸»é¡µé¢ <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> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="审æ¹ç®¡ç" @back="goBack" /> <!-- æç´¢åçéåºå --> <view class="search-filter-section"> @@ -86,6 +79,7 @@ import { ledgerListPage } from "@/api/cooperativeOffice/collaborativeApproval"; import PageHeader from "@/components/PageHeader.vue"; // æç´¢å ³é®è¯ const searchKeyword = ref(""); @@ -157,72 +151,7 @@ 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; src/pages/index.vue
@@ -5,7 +5,7 @@ <up-text type="primary" :text="userStore.currentFactoryName" @click="show = true" size="18" class="factoryName" suffixIcon="arrow-right" :iconStyle="iconStyle"></up-text> </view> <up-picker :show="show" :columns="factoryList" @confirm="changeFactory"></up-picker> <up-picker :show="show" :columns="factoryList" @confirm="changeFactory" @cancel="show = false"></up-picker> </view> <view class="hero-section"> @@ -308,6 +308,16 @@ url: '/pages/sales/receiptPayment/index' }); break; case '忬¾æµæ°´': uni.navigateTo({ url: '/pages/sales/receiptPaymentHistory/index' }); break; case '客æ·å¾æ¥': uni.navigateTo({ url: '/pages/sales/receiptPaymentLedger/index' }); break; case 'åå审æ¹': uni.navigateTo({ url: '/pages/cooperativeOffice/collaborativeApproval/index' src/pages/sales/invoiceLedger/detail.vue
@@ -1,13 +1,7 @@ <template> <view class="account-detail"> <van-nav-bar title="ç¼è¾å¼ç¥¨å°è´¦" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <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> src/pages/sales/invoiceLedger/index.vue
@@ -1,14 +1,7 @@ <template> <view class="sales-account"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="å¼ç¥¨å°è´¦" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="å¼ç¥¨å°è´¦" @back="goBack" /> <!-- æç´¢åçéåºåï¼ä¿æä¸éå®å°è´¦é£æ ¼ä¸è´ï¼ --> <view class="search-filter-section"> @@ -103,6 +96,7 @@ <van-button type="danger" size="small" plain class="action-btn" :disabled="item.invoicePerson !== userStore.nickName" @click="handleDelete(item)" @@ -112,6 +106,7 @@ <van-button type="default" size="small" plain class="action-btn" v-if="item.invoiceFileName" @click="openFileActions(item.commonFiles || [])" @@ -121,7 +116,6 @@ <van-button type="primary" size="small" plain class="action-btn" v-else :disabled="item.invoicePerson !== userStore.nickName" src/pages/sales/invoicingRegistration/add.vue
@@ -1,14 +1,7 @@ <template> <view class="account-detail"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="æ°å¢å¼ç¥¨ç»è®°" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <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"> src/pages/sales/invoicingRegistration/index.vue
@@ -1,14 +1,7 @@ <template> <view class="sales-account"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="å¼ç¥¨ç»è®°" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="å¼ç¥¨ç»è®°" @back="goBack" /> <!-- æç´¢åçéåºå --> <view class="search-filter-section"> @@ -246,13 +239,20 @@ .header-center { flex: 1; text-align: center; 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 { src/pages/sales/invoicingRegistration/view.vue
@@ -1,14 +1,7 @@ <template> <view class="account-view"> <!-- 顶鍿 颿 --> <van-nav-bar title="å¼ç¥¨ç»è®°è¯¦æ " left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="å¼ç¥¨ç»è®°è¯¦æ " @back="goBack" /> <!-- åºæ¬ä¿¡æ¯å±ç¤º --> <view class="info-section"> src/pages/sales/receiptPayment/add.vue
@@ -1,14 +1,7 @@ <template> <view class="account-detail"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="æ°å¢å款" left-text="è¿å" left-arrow @click-left="onClickLeft" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <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"> src/pages/sales/receiptPayment/index.vue
@@ -1,14 +1,7 @@ <template> <view class="receipt-payment"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="忬¾ç»è®°" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="忬¾ç»è®°" @back="goBack" /> <!-- æç´¢åçéåºå --> <view class="search-filter-section"> src/pages/sales/receiptPaymentHistory/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,371 @@ <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.salesContractNo }}</text> </view> <view class="item-tag" :class="getTagClass(item.receiptPaymentType)"> <text class="tag-text">{{ formatReceiptType(item.receiptPaymentType) }}</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.customerContractNo }}</text> </view> <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.projectName }}</text> </view> <view class="detail-row"> <text class="detail-label">忬¾æ¥æ</text> <text class="detail-value">{{ item.receiptPaymentDate }}</text> </view> <view class="detail-row"> <text class="detail-label">忬¾éé¢(å )</text> <text class="detail-value highlight">{{ formatAmount(item.receiptPaymentAmount) }}</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.createTime }}</text> </view> </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 { receiptPaymentHistoryListPage } from "@/api/salesManagement/receiptPayment.js"; // æç´¢è¡¨å 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 }; receiptPaymentHistoryListPage(params).then((res) => { tableData.value = res.records; }).catch(() => { uni.showToast({ title: 'æ¥è¯¢å¤±è´¥', icon: 'error' }); }); }; // æ ¼å¼å忬¾æ¹å¼ const formatReceiptType = (type) => { if (type == 0) { return "çµæ±"; } else if (type == 1) { return "æ¿å "; } else { return "æªç¥"; } }; // è·åæ ç¾æ ·å¼ç±» const getTagClass = (type) => { if (type == 0) { return "tag-electric"; } else if (type == 1) { return "tag-acceptance"; } else { return "tag-unknown"; } }; // æ ¼å¼åéé¢ const formatAmount = (amount) => { return amount ? parseFloat(amount).toFixed(2) : '0.00'; }; 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; } .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> src/pages/sales/receiptPaymentLedger/detail.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,290 @@ <template> <view class="receipt-payment-detail"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="客æ·å¾æ¥è¯¦æ " @back="goBack" /> <!-- ç»è®¡ä¿¡æ¯ --> <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">{{ formatAmount(invoiceTotal) }}</text> </view> <view class="summary-item"> <text class="summary-label">忬¾æ»éé¢</text> <text class="summary-value highlight">{{ formatAmount(receiptTotal) }}</text> </view> <view class="summary-item"> <text class="summary-label">åºæ¶æ»éé¢</text> <text class="summary-value danger">{{ formatAmount(unReceiptTotal) }}</text> </view> </view> <!-- 忬¾è®°å½æç»å表 --> <view class="detail-list" v-if="tableData.length > 0"> <view v-for="(item, index) in tableData" :key="index" class="detail-item"> <view class="item-header"> <view class="item-left"> <view class="record-icon"> <up-icon name="file-text" size="16" color="#ffffff"></up-icon> </view> <text class="item-index">{{ index + 1 }}</text> </view> <view class="item-date">{{ item.happenTime }}</view> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">å¼ç¥¨éé¢(å )</text> <text class="detail-value">{{ formatAmount(item.invoiceAmount) }}</text> </view> <view class="detail-row"> <text class="detail-label">忬¾éé¢(å )</text> <text class="detail-value highlight">{{ formatAmount(item.receiptAmount) }}</text> </view> <view class="detail-row"> <text class="detail-label">åºæ¶éé¢(å )</text> <text class="detail-value danger">{{ formatAmount(item.unReceiptAmount) }}</text> </view> </view> </view> </view> <view v-else class="no-data"> <text>ææ åæ¬¾è®°å½</text> </view> </view> </template> <script setup> import { ref, computed, onMounted } from 'vue'; import { onShow } from '@dcloudio/uni-app'; import { customerInteractions } from "@/api/salesManagement/receiptPayment.js"; // 客æ·ä¿¡æ¯ const customerId = ref(''); // è¡¨æ ¼æ°æ® const tableData = ref([]); const invoiceTotal = computed(() => { return tableData.value.reduce((sum, item) => { return sum + (parseFloat(item.invoiceAmount) || 0); }, 0); }); const receiptTotal = computed(() => { return tableData.value.reduce((sum, item) => { return sum + (parseFloat(item.receiptAmount) || 0); }, 0); }); const unReceiptTotal = computed(() => { return tableData.value.reduce((sum, item) => { return sum + (parseFloat(item.unReceiptAmount) || 0); }, 0); }); // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack(); }; // è·å页é¢åæ° const getPageParams = () => { const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const options = currentPage.options; if (options.customerId) { customerId.value = options.customerId; } }; // æ¥è¯¢å表 const getList = () => { if (!customerId.value) { uni.showToast({ title: '客æ·ä¿¡æ¯ç¼ºå¤±', icon: 'error' }); return; } const param = { customerId: customerId.value, }; customerInteractions(param).then((res) => { tableData.value = res.data; }).catch(() => { uni.showToast({ title: 'æ¥è¯¢å¤±è´¥', icon: 'error' }); }); }; // æ ¼å¼åéé¢ const formatAmount = (amount) => { return amount ? parseFloat(amount).toFixed(2) : '0.00'; }; onShow(() => { // 页颿¾ç¤ºæ¶è·ååæ°å¹¶å·æ°å表 getPageParams(); getList(); }); onMounted(() => { // 页é¢å è½½æ¶è·ååæ°å¹¶å·æ°å表 getPageParams(); getList(); }); </script> <style scoped lang="scss"> .receipt-payment-detail { min-height: 100vh; background: #f8f9fa; position: relative; } .u-divider { margin: 0 !important; } .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; } .summary-value.danger { color: #ff4757; font-weight: 600; } .detail-list { padding: 20px; } .detail-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: 10px 0; display: flex; align-items: center; justify-content: space-between; } .item-left { display: flex; align-items: center; gap: 8px; } .record-icon { width: 24px; height: 24px; background: #2979ff; border-radius: 4px; display: flex; align-items: center; justify-content: center; } .item-index { font-size: 14px; color: #333; font-weight: 500; } .item-date { font-size: 12px; color: #666; } .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; } .detail-value.highlight { color: #2979ff; font-weight: 500; } .detail-value.danger { color: #ff4757; font-weight: 500; } .no-data { padding: 40px 0; text-align: center; color: #999; } </style> src/pages/sales/receiptPaymentLedger/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,300 @@ <template> <view class="receipt-payment-ledger"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <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="handleQuery" /> </view> <view class="search-button" @click="handleQuery"> <up-icon name="search" size="24" color="#999"></up-icon> </view> </view> </view> <!-- 客æ·å表 --> <view class="customer-list-container"> <view class="customer-list" v-if="tableData.length > 0"> <view v-for="(item, index) in tableData" :key="item.id" class="customer-item" @click="rowClickMethod(item)" > <view class="item-header"> <view class="item-left"> <view class="customer-icon"> <up-icon name="file-text" size="16" color="#ffffff"></up-icon> </view> <text class="customer-name">{{ item.customerName }}</text> </view> <view class="item-right"> <up-icon name="arrow-right" size="16" color="#999"></up-icon> </view> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">å¼ç¥¨éé¢(å )</text> <text class="detail-value">{{ formattedNumber(item.invoiceTotal) }}</text> </view> <view class="detail-row"> <text class="detail-label">忬¾éé¢(å )</text> <text class="detail-value">{{ formattedNumber(item.receiptPaymentAmount) }}</text> </view> <view class="detail-row"> <text class="detail-label">åºæ¶éé¢(å )</text> <text class="detail-value highlight danger">{{ formattedNumber(item.unReceiptPaymentAmount) }}</text> </view> </view> </view> </view> <view v-else class="no-data"> <text>ææ å®¢æ·æ°æ®</text> </view> </view> </view> </template> <script setup> import { onMounted, ref, reactive, toRefs } from "vue"; import { onShow } from '@dcloudio/uni-app'; import { invoiceLedgerSalesAccount } from "@/api/salesManagement/invoiceLedger"; const tableData = ref([]); const page = reactive({ current: -1, size: -1, }); const data = reactive({ searchForm: { searchText: "", invoiceDate: "", }, }); const { searchForm } = toRefs(data); // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack(); }; // æ¥è¯¢å表 const handleQuery = () => { getList(); }; const getList = () => { invoiceLedgerSalesAccount({ ...searchForm.value, ...page }).then((res) => { tableData.value = res.data.records; }).catch(() => { uni.showToast({ title: 'æ¥è¯¢å¤±è´¥', icon: 'error' }); }); }; const formattedNumber = (value) => { return parseFloat(value || 0).toFixed(2); }; const rowClickMethod = (row) => { // 跳转å°åæ¬¾è®°å½æç»é¡µé¢ uni.navigateTo({ url: `/pages/sales/receiptPaymentLedger/detail?customerId=${row.id}` }); }; onShow(() => { // 页颿¾ç¤ºæ¶å·æ°å表 getList(); }); onMounted(() => { getList(); }); </script> <style scoped lang="scss"> .u-divider { margin: 0 !important; } .receipt-payment-ledger { 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; } .customer-list-container { padding: 20px; } .customer-list { display: flex; flex-direction: column; gap: 16px; } .customer-item { background: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); padding: 0 16px; transition: all 0.3s ease; &:active { transform: scale(0.98); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); } } .item-header { padding: 16px 0; display: flex; align-items: center; justify-content: space-between; } .item-left { display: flex; align-items: center; gap: 8px; } .item-right { display: flex; align-items: center; gap: 8px; } .customer-icon { width: 24px; height: 24px; background: #2979ff; border-radius: 4px; display: flex; align-items: center; justify-content: center; } .customer-name { font-size: 14px; color: #333; font-weight: 500; } .item-index { font-size: 12px; color: #999; background: #f5f5f5; padding: 2px 8px; border-radius: 12px; } .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; } .detail-value.highlight { color: #2979ff; font-weight: 500; } .detail-value.danger { color: #ff4757; font-weight: 500; } .no-data { padding: 40px 0; text-align: center; color: #999; } </style> src/pages/sales/salesAccount/detail.vue
@@ -1,14 +1,7 @@ <template> <view class="account-detail"> <!-- 顶鍿 颿 --> <van-nav-bar title="å°è´¦è¯¦æ " left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="å°è´¦è¯¦æ " @back="goBack" /> <!-- 表ååºå --> <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"> @@ -796,9 +789,6 @@ font-weight: 600; color: #333; } .add-btn { border-radius: 0.25rem; } .product-card { background: #FFFFFF; box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); @@ -846,9 +836,6 @@ } .product-form { margin-bottom: 1rem; } .del-btn { border-radius: 0.25rem; } .footer-btns { position: fixed; src/pages/sales/salesAccount/index.vue
@@ -1,14 +1,7 @@ <template> <view class="sales-account"> <!-- 页é¢å¤´é¨ --> <van-nav-bar title="éå®å°è´¦" left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="éå®å°è´¦" @back="goBack" /> <!-- æç´¢åçéåºå --> <view class="search-filter-section"> @@ -103,6 +96,7 @@ import { onShow } from '@dcloudio/uni-app'; import {ledgerListPage} from "@/api/salesManagement/salesLedger"; import useUserStore from "@/store/modules/user"; import PageHeader from "@/components/PageHeader.vue"; const userStore = useUserStore() // æç´¢å ³é®è¯ @@ -195,70 +189,7 @@ 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; @@ -405,7 +336,7 @@ .fab-button { position: fixed; bottom: 30px; bottom: calc(30px + env(safe-area-inset-bottom)); right: 30px; width: 56px; height: 56px; @@ -416,5 +347,6 @@ justify-content: center; box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); z-index: 1000; /* ç¡®ä¿æµ®å¨æé®ä¸è¢«åºé¨å®å ¨åºå鮿¡ */ } </style> src/pages/sales/salesAccount/view.vue
@@ -1,14 +1,7 @@ <template> <view class="account-view"> <!-- 顶鍿 颿 --> <van-nav-bar title="å°è´¦è¯¦æ " left-text="è¿å" left-arrow @click-left="goBack" fixed placeholder /> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="å°è´¦è¯¦æ " @back="goBack" /> <!-- åºæ¬ä¿¡æ¯å±ç¤º --> <view class="info-section"> src/static/scss/global.scss
@@ -2,6 +2,21 @@ text-align: center; } /* ç§»å¨ç«¯å¯é çå± ä¸æ¹æ³ */ .center-absolute { display: flex; justify-content: center; align-items: center; position: absolute; left: 0; right: 0; pointer-events: none; } .center-absolute > * { pointer-events: auto; } .font-13 { font-size: 13px; }