<template>
|
<view class="invoice-page">
|
<view class="search-bar">
|
<view class="search-box">
|
<image src="/static/icon/ic_search2@2x.png" mode="widthFix"></image>
|
<input
|
v-model="keyword"
|
class="search-input"
|
type="text"
|
placeholder="搜索订单编号"
|
@confirm="handleSearch"
|
/>
|
</view>
|
</view>
|
|
<scroll-view scroll-y class="page-scroll" @scrolltolower="handleScrollTolower">
|
<view v-if="currentTab === 'apply'" class="card-list">
|
<view v-for="item in applyList" :key="item.id" class="invoice-card apply-card">
|
<view class="order-no">
|
<text>订单编号:{{ item.code }}</text>
|
<view class="mode-tag city-tag" v-if="item.type === 1">同城寄送</view>
|
<view class="mode-tag local-tag" v-else>就地寄存</view>
|
</view>
|
<view class="address-group">
|
<view class="address-row">
|
<view class="address-tag send-tag" style="width: 60rpx; height: 60rpx;" v-if="item.type === 0">
|
<image style="width: 100%; height: 100%;" src="/static/icon/ic_store@2x.png" mode="aspectFit"></image>
|
</view>
|
<view class="address-tag send-tag" v-else>寄</view>
|
<view class="address-copy">
|
<view class="address-title-row">
|
<text class="address-title">{{ item.depositShopName }}</text>
|
<u-icon name="arrow-right" size="14" color="#40454d"></u-icon>
|
</view>
|
<text class="address-user">{{ item.depositShopAddress }}</text>
|
</view>
|
</view>
|
<view class="address-dash" v-if="item.type === 1"></view>
|
<view class="address-row" v-if="item.type === 1">
|
<view class="address-tag receive-tag">收</view>
|
<view class="address-copy">
|
<view class="address-title-row">
|
<text class="address-title">{{ item.takeShopId ? item.takeShopName : item.takeLocation }}</text>
|
<u-icon name="arrow-right" size="14" color="#40454d"></u-icon>
|
</view>
|
<text class="address-user">{{ item.takeShopId ? item.takeShopAddress : item.takeLocationRemark }}</text>
|
</view>
|
</view>
|
</view>
|
|
<view class="goods-line">
|
<text class="goods-text">{{ item.goodsText }}</text>
|
<u-icon name="arrow-down" size="14" color="#a2a7b1"></u-icon>
|
</view>
|
|
<view class="price-row">
|
<view class="price-copy">
|
<text class="price-label">实付款:</text>
|
<text class="price-value">¥{{((item.estimatedAmount || 0)/100).toFixed(2) }}</text>
|
</view>
|
<!-- <view class="action-btn primary-btn" @tap="goInvoiceRequest(item)">申请开票</view> -->
|
</view>
|
</view>
|
</view>
|
|
<view v-else class="card-list">
|
<view v-for="item in historyList" :key="item.id" class="invoice-card history-card">
|
<view class="history-head">
|
<text class="company-name">{{ item.name }}</text>
|
<text class="history-status" :class="item.status === 1 ? 'done' : item.status === 99 ? 'failed' : 'processing'">{{ item.status == 1 ? '已开票' : item.status == 99 ? '开具失败' : '开票中' }}</text>
|
</view>
|
<view class="history-subline">
|
<text>{{ item.invoiceType === 0 ? '电子普通发票' : '电子专用发票' }}</text>
|
<text class="sub-sep">|</text>
|
<text>发票金额:</text>
|
<text class="history-amount">¥{{((item.invoiceAmount || 0)/100).toFixed(2) }}</text>
|
</view>
|
<view class="history-divider"></view>
|
<view class="history-detail">
|
<view class="detail-item">开票编号:{{ item.orderNo }}</view>
|
<view class="detail-item">发票号码:{{ item.invoiceNo || '' }}</view>
|
<view class="detail-item">申请时间:{{ item.createTime }}</view>
|
<view v-if="item.remark" class="detail-item fail-row">失败理由:<text class="fail-text">{{ item.remark }}</text></view>
|
</view>
|
|
<view v-if="item.actions && item.actions.length" class="history-actions">
|
<view
|
v-for="action in item.actions"
|
:key="action.text"
|
class="action-btn"
|
:class="action.primary ? 'primary-btn' : 'ghost-btn'"
|
@tap="handleAction(action, item)"
|
>
|
{{ action.text }}
|
</view>
|
</view>
|
</view>
|
</view>
|
</scroll-view>
|
|
<u-popup :show="showEmailPopup" mode="center" bgColor="transparent" @close="closeEmailPopup">
|
<view class="email-popup">
|
<view class="email-title">发送至邮箱</view>
|
<view class="email-input-wrap">
|
<input v-model="email" class="email-input" type="text" placeholder="请输入邮箱" />
|
<u-icon v-if="email" name="close-circle-fill" size="20" color="#a7a7a7" @tap="email = ''"></u-icon>
|
</view>
|
<view class="email-footer">
|
<view class="popup-btn popup-btn-cancel" @tap="closeEmailPopup">取消</view>
|
<view class="popup-btn popup-btn-confirm" @tap="confirmSendEmail">确认发送</view>
|
</view>
|
</view>
|
</u-popup>
|
|
<view class="bottom-tabs">
|
<view
|
v-for="tab in tabs"
|
:key="tab.value"
|
class="bottom-tab"
|
:class="{ active: currentTab === tab.value }"
|
@tap="currentTab = tab.value"
|
>
|
<image
|
v-if="getTabIcon(tab)"
|
class="tab-icon"
|
:src="getTabIcon(tab)"
|
mode="aspectFit"
|
></image>
|
<view v-else class="tab-icon placeholder-icon"></view>
|
<text class="tab-label">{{ tab.label }}</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
currentTab: 'apply',
|
keyword: '',
|
showEmailPopup: false,
|
email: '',
|
currentInvoiceRecordId: '',
|
currentYear: '近一年',
|
tabs: [
|
{
|
label: '开票',
|
value: 'apply',
|
icon: '/shop/static/icon/nav_kaipiao@2x.png',
|
activeIcon: '/shop/static/icon/nav_kaipiao_sel@2x.png'
|
},
|
{
|
label: '开票历史',
|
value: 'history',
|
icon: '/shop/static/icon/nav_lishi@2x.png',
|
activeIcon: '/shop/static/icon/nav_lishi_sel@2x.png'
|
}
|
],
|
applyList: [],
|
page: 1,
|
capacity: 10,
|
isRequest: true,
|
historyPage: 1,
|
historyCapacity: 10,
|
historyIsRequest: true,
|
historyList: [],
|
};
|
},
|
watch: {
|
currentTab() {
|
if (this.currentTab === 'apply') {
|
this.page = 1
|
this.applyList = []
|
this.isRequest = true
|
this.getApplyList()
|
} else if (this.currentTab === 'history') {
|
this.historyPage = 1
|
this.historyList = []
|
this.historyIsRequest = true
|
this.getHistoryList()
|
}
|
}
|
},
|
onLoad() {
|
this.getApplyList()
|
},
|
methods: {
|
handleScrollTolower() {
|
if (this.currentTab === 'apply') {
|
this.getApplyList()
|
} else if (this.currentTab === 'history') {
|
this.getHistoryList()
|
}
|
},
|
async getApplyList() {
|
if (!this.isRequest) return
|
const res = await this.$u.api.myOrderPage({
|
capacity: this.capacity,
|
page: this.page,
|
model: {
|
invoiceStatus: 1,
|
keyword: this.keyword
|
}
|
})
|
if (res.code === 200) {
|
const list = res.data.records || []
|
list.forEach(item => {
|
if (item.detailList && item.detailList.length > 0) {
|
item.goodsText = item.detailList.map(d => d.luggageName + '*' + d.num).join('、')
|
}
|
})
|
this.applyList = [...this.applyList, ...list]
|
this.page++
|
console.log(res.data.total, this.applyList.length)
|
if (this.applyList.length >= res.data.total) {
|
this.isRequest = false
|
}
|
}
|
},
|
async getHistoryList() {
|
if (!this.historyIsRequest) return
|
const res = await this.$u.api.invoicePage({
|
page: this.historyPage,
|
capacity: this.historyCapacity,
|
model: {
|
orderNo: this.keyword
|
}
|
})
|
if (res.code === 200) {
|
const list = res.data.records || []
|
list.forEach(item => {
|
if (item.status === 1) {
|
item.actions = [{ text: '发送至邮箱', primary: true }]
|
}
|
})
|
this.historyList = [...this.historyList, ...list]
|
this.historyPage++
|
if (this.historyList.length >= res.data.total) {
|
this.historyIsRequest = false
|
}
|
}
|
},
|
handleSearch() {
|
if (this.currentTab === 'apply') {
|
this.page = 1
|
this.applyList = []
|
this.isRequest = true
|
this.getApplyList()
|
} else if (this.currentTab === 'history') {
|
this.historyPage = 1
|
this.historyList = []
|
this.historyIsRequest = true
|
this.getHistoryList()
|
}
|
},
|
getTabIcon(tab) {
|
return this.currentTab === tab.value ? tab.activeIcon : tab.icon;
|
},
|
goInvoiceRequest(item) {
|
const params = []
|
if (item && item.id) params.push(`id=${item.id}`)
|
if (item && item.code) params.push(`orderNo=${item.code}`)
|
if (item && item.estimatedAmount) params.push(`invoiceAmount=${((item.estimatedAmount || 0) / 100).toFixed(2)}`)
|
const query = params.length ? `?${params.join('&')}` : ''
|
uni.navigateTo({
|
url: `/shop/pages/Invoice-request/Invoice-request${query}`
|
});
|
},
|
handleAction(action, item) {
|
if (action.text === '发送至邮箱') {
|
this.currentInvoiceRecordId = item.id
|
this.showEmailPopup = true;
|
return;
|
}
|
|
if (action.text === '申请开票') {
|
this.goInvoiceRequest();
|
}
|
},
|
closeEmailPopup() {
|
this.showEmailPopup = false;
|
},
|
async confirmSendEmail() {
|
if (!this.email) {
|
uni.showToast({ title: '请输入邮箱', icon: 'none' });
|
return;
|
}
|
const res = await this.$u.api.sendEmail({
|
email: this.email,
|
invoiceRecordId: this.currentInvoiceRecordId
|
})
|
if (res.code === 200) {
|
uni.showToast({ title: '发送成功', icon: 'success' });
|
this.showEmailPopup = false;
|
this.email = '';
|
}
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.invoice-page {
|
min-height: 100vh;
|
background: linear-gradient(180deg, #f8f9fc 0%, #f4f6fb 100%);
|
}
|
|
.mode-tag {
|
width: 112rpx;
|
height: 38rpx;
|
line-height: 38rpx;
|
border-radius: 8rpx;
|
display: flex;
|
align-items: baseline;
|
justify-content: center;
|
font-weight: 400;
|
font-size: 24rpx;
|
color: #FFFFFF;
|
margin-right: 14rpx;
|
flex-shrink: 0;
|
}
|
|
.local-tag {
|
background: #18abf8;
|
// background: linear-gradient(90deg, #18abf8 0%, #39c5ff 100%);
|
}
|
|
.city-tag {
|
// background: linear-gradient(90deg, #ff8b28 0%, #ffb14f 100%);
|
margin-right: 0;
|
background: #ff8b28;
|
margin-bottom: 8rpx;
|
}
|
|
.search-bar {
|
display: flex;
|
align-items: center;
|
gap: 18rpx;
|
padding: 18rpx 24rpx 16rpx;
|
background: #ffffff;
|
}
|
|
.search-box {
|
width: 100%;
|
height: 100%;
|
padding: 0 30rpx;
|
box-sizing: border-box;
|
display: flex;
|
align-items: center;
|
background: #EEEEEE;
|
border-radius: 158rpx;
|
border: 1rpx solid #EEEEEE;
|
}
|
|
.search-bar image {
|
width: 32rpx;
|
height: 32rpx;
|
margin-right: 16rpx;
|
}
|
|
.search-input {
|
flex: 1;
|
height: 72rpx;
|
padding: 0 24rpx 0 0;
|
font-size: 28rpx;
|
color: #2f3137;
|
}
|
|
.search-bar {
|
position: relative;
|
}
|
|
.search-bar > * {
|
position: relative;
|
z-index: 1;
|
}
|
|
.page-scroll {
|
height: calc(100vh - 124rpx - 124rpx);
|
}
|
|
.card-list {
|
padding: 20rpx 30rpx;
|
box-sizing: border-box;
|
}
|
|
.invoice-card {
|
padding: 30rpx;
|
box-sizing: border-box;
|
margin-bottom: 20rpx;
|
background: #ffffff;
|
border-radius: 20rpx;
|
box-shadow: 0 12rpx 30rpx rgba(45, 82, 134, 0.04);
|
}
|
|
.order-no {
|
width: 100%;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
text {
|
font-size: 28rpx;
|
line-height: 40rpx;
|
color: #9ca3af;
|
}
|
}
|
|
.address-group {
|
position: relative;
|
margin-top: 24rpx;
|
}
|
|
.address-row {
|
display: flex;
|
align-items: flex-start;
|
gap: 18rpx;
|
}
|
|
.address-tag {
|
flex-shrink: 0;
|
width: 40rpx;
|
height: 40rpx;
|
line-height: 40rpx;
|
border-radius: 50%;
|
text-align: center;
|
font-size: 24rpx;
|
font-weight: 600;
|
color: #ffffff;
|
}
|
|
.send-tag {
|
background: linear-gradient(180deg, #4bc7ff 0%, #1ea4ff 100%);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
image {
|
width: 28rpx;
|
height: 28rpx;
|
}
|
}
|
|
.receive-tag {
|
background: linear-gradient(180deg, #ffb248 0%, #ff8600 100%);
|
}
|
|
.address-copy {
|
flex: 1;
|
min-width: 0;
|
}
|
|
.address-title-row {
|
display: flex;
|
align-items: center;
|
gap: 8rpx;
|
}
|
|
.address-title {
|
flex: 1;
|
font-size: 38rpx;
|
font-weight: 700;
|
line-height: 52rpx;
|
color: #252a33;
|
}
|
|
.address-user {
|
display: block;
|
margin-top: 8rpx;
|
font-size: 30rpx;
|
line-height: 42rpx;
|
color: #9aa0aa;
|
}
|
|
.address-dash {
|
width: 0;
|
height: 26rpx;
|
margin: 8rpx 0 8rpx 20rpx;
|
border-left: 2rpx dashed #e1e5ec;
|
}
|
|
.goods-line {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 16rpx;
|
padding: 20rpx;
|
box-sizing: border-box;
|
margin-top: 22rpx;
|
border-radius: 14rpx;
|
background: #f6f7fa;
|
}
|
|
.goods-text {
|
flex: 1;
|
font-size: 30rpx;
|
line-height: 42rpx;
|
color: #686f7c;
|
}
|
|
.price-row {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 20rpx;
|
margin-top: 26rpx;
|
}
|
|
.price-copy {
|
display: flex;
|
align-items: baseline;
|
}
|
|
.price-label {
|
font-size: 32rpx;
|
line-height: 44rpx;
|
color: #353b44;
|
}
|
|
.price-value {
|
font-size: 44rpx;
|
font-weight: 700;
|
line-height: 56rpx;
|
color: #252a33;
|
}
|
|
.action-btn {
|
display: inline-flex;
|
align-items: center;
|
justify-content: center;
|
min-width: 168rpx;
|
height: 68rpx;
|
padding: 0 26rpx;
|
border-radius: 999rpx;
|
font-size: 30rpx;
|
font-weight: 500;
|
}
|
|
.primary-btn {
|
background: linear-gradient(135deg, #3bc6ff 0%, #1ea5ff 100%);
|
color: #ffffff;
|
box-shadow: 0 10rpx 22rpx rgba(30, 165, 255, 0.22);
|
}
|
|
.ghost-btn {
|
border: 2rpx solid #d9dce4;
|
background: #ffffff;
|
color: #6e7581;
|
}
|
|
.history-head {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 20rpx;
|
}
|
|
.company-name {
|
flex: 1;
|
font-size: 38rpx;
|
font-weight: 700;
|
line-height: 52rpx;
|
color: #252a33;
|
}
|
|
.history-status {
|
flex-shrink: 0;
|
font-weight: 400;
|
font-size: 26rpx;
|
}
|
|
.history-status.processing {
|
color: #FF0000;
|
}
|
|
.history-status.done,
|
.history-amount {
|
color: #10B2FA;
|
}
|
|
.history-status.failed {
|
color: #999999;
|
}
|
|
.history-subline {
|
display: flex;
|
align-items: center;
|
flex-wrap: wrap;
|
gap: 8rpx;
|
margin-top: 14rpx;
|
font-size: 28rpx;
|
line-height: 40rpx;
|
color: #7b818c;
|
}
|
|
.sub-sep {
|
color: #d3d7df;
|
}
|
|
.history-divider {
|
height: 2rpx;
|
margin: 22rpx 0;
|
background: #f1f3f6;
|
}
|
|
.history-detail {
|
font-size: 28rpx;
|
line-height: 44rpx;
|
color: #a1a7b2;
|
}
|
|
.detail-item + .detail-item {
|
margin-top: 6rpx;
|
}
|
|
.fail-row {
|
margin-top: 10rpx;
|
}
|
|
.fail-text {
|
color: #ff4b4b;
|
}
|
|
.history-actions {
|
display: flex;
|
justify-content: flex-end;
|
gap: 18rpx;
|
margin-top: 24rpx;
|
}
|
|
.email-popup {
|
width: 680rpx;
|
overflow: hidden;
|
background: #ffffff;
|
border-radius: 22rpx;
|
}
|
|
.email-title {
|
padding: 50rpx 32rpx 38rpx;
|
text-align: center;
|
font-size: 40rpx;
|
font-weight: 700;
|
line-height: 56rpx;
|
color: #222222;
|
}
|
|
.email-input-wrap {
|
display: flex;
|
align-items: center;
|
margin: 0 54rpx 44rpx;
|
padding: 0 24rpx 0 34rpx;
|
height: 84rpx;
|
border-radius: 999rpx;
|
background: #f6f6f6;
|
}
|
|
.email-input {
|
flex: 1;
|
height: 84rpx;
|
font-size: 34rpx;
|
text-align: center;
|
color: #4a4a4a;
|
}
|
|
.email-footer {
|
display: flex;
|
align-items: center;
|
height: 100rpx;
|
border-top: 1rpx solid #f1f1f1;
|
}
|
|
.popup-btn {
|
flex: 1;
|
height: 100rpx;
|
line-height: 100rpx;
|
text-align: center;
|
font-size: 36rpx;
|
font-weight: 500;
|
}
|
|
.popup-btn-cancel {
|
color: #999999;
|
}
|
|
.popup-btn-confirm {
|
color: #1eb6ff;
|
border-left: 1rpx solid #f1f1f1;
|
}
|
|
.bottom-tabs {
|
display: flex;
|
align-items: center;
|
justify-content: space-around;
|
height: 124rpx;
|
background: rgba(255, 255, 255, 0.98);
|
box-shadow: 0 -8rpx 30rpx rgba(35, 60, 96, 0.05);
|
}
|
|
.bottom-tab {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
gap: 8rpx;
|
color: #a4a9b2;
|
}
|
|
.bottom-tab.active {
|
color: #1ea5ff;
|
}
|
|
.tab-icon {
|
width: 52rpx;
|
height: 52rpx;
|
}
|
|
.placeholder-icon {
|
border-radius: 10rpx;
|
background: #dfe4ec;
|
}
|
|
.tab-label {
|
font-size: 26rpx;
|
line-height: 36rpx;
|
font-weight: 500;
|
}
|
</style>
|