feat: 积分商城-基本实现拆单、确认收货2
This commit is contained in:
@@ -3,7 +3,7 @@ layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="我的订单" left-arrow left-text="返回" @click-left="back" fixed placeholder></van-nav-bar>
|
||||
<div class="order-page">
|
||||
<div class="order-page order-list-page">
|
||||
<section class="order-header">
|
||||
<div class="points-content">
|
||||
<div class="points-label">剩余积分</div>
|
||||
@@ -14,69 +14,125 @@ layout("/layouts/platform_h5.html"){
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<van-sticky>
|
||||
<van-sticky :offset-top="0">
|
||||
<div class="filter-bar">
|
||||
<van-tabs
|
||||
v-model="pageForm.orderState"
|
||||
class="custom-tabs"
|
||||
line-width="20px"
|
||||
color="#1989fa"
|
||||
title-active-color="#1989fa"
|
||||
title-inactive-color="#666"
|
||||
:border="false"
|
||||
@change="doSearch"
|
||||
>
|
||||
<van-tab v-for="tab in tabList" :key="tab.code" :name="tab.code" :title="tab.name"></van-tab>
|
||||
</van-tabs>
|
||||
<div class="grid-icon">
|
||||
<van-icon name="apps-o" size="20" color="#1989fa"></van-icon>
|
||||
</div>
|
||||
<div class="custom-tab-wrap">
|
||||
<div class="tab-group tab-group--normal">
|
||||
<div
|
||||
v-for="tab in normalTabList"
|
||||
:key="tab.code"
|
||||
class="tab-item"
|
||||
:class="{ 'tab-item--active': Number(pageForm.orderState) === Number(tab.code) }"
|
||||
@click="onTabClick(tab.code)"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-divider">|</div>
|
||||
<div class="tab-group tab-group--special">
|
||||
<div
|
||||
v-for="tab in specialTabList"
|
||||
:key="tab.code"
|
||||
class="tab-item"
|
||||
:class="{ 'tab-item--active': Number(pageForm.orderState) === Number(tab.code) }"
|
||||
@click="onTabClick(tab.code)"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<van-list v-if="tableData.length" class="list-container" v-model="tableLoading" :finished="tableFinished" finished-text="没有更多了" @load="pageData">
|
||||
<article class="order-card" v-for="item in tableData" :key="item.id || item.orderId">
|
||||
<header class="card-header">
|
||||
<div class="shop-info">
|
||||
<span class="shop-name">{{ item.supplierName || "积分商城" }}</span>
|
||||
<van-icon name="arrow" color="#ccc" size="12"></van-icon>
|
||||
</div>
|
||||
<span class="status-text" :class="getStatusClass(item.orderState)">{{ orderStateName(item.orderState) }}</span>
|
||||
</header>
|
||||
<van-pull-refresh v-model="refreshing" class="list-container" @refresh="onRefresh">
|
||||
<van-list v-if="tableData.length" v-model="tableLoading" :finished="tableFinished" finished-text="没有更多了" @load="pageData">
|
||||
<article class="order-card" v-for="item in tableData" :key="item.id || item.orderId">
|
||||
<header class="card-header">
|
||||
<div class="shop-info">
|
||||
<span class="shop-name">{{ item.supplierName || "积分商城" }}</span>
|
||||
<van-icon name="arrow" color="#ccc" size="12"></van-icon>
|
||||
<span class="order-type-name">{{ getOrderTypeName(item.orderType) }}</span>
|
||||
</div>
|
||||
<div class="status-box">
|
||||
<span class="status-text" :class="'status-bg-' + getStatusClass(item.orderState)">{{ orderStateName(item.orderState) }}</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="product-row" v-if="item.productImgList && item.productImgList.length">
|
||||
<van-image v-for="(img, index) in item.productImgList.slice(0, 3)" :key="index" :src="img" fit="cover" radius="4"></van-image>
|
||||
</div>
|
||||
<div class="card-body" v-if="item.productImgList && item.productImgList.length">
|
||||
<div class="multi-prod-view" v-if="item.productImgList.length > 1">
|
||||
<div class="imgs-scroll">
|
||||
<div class="img-box" v-for="(img, index) in item.productImgList.slice(0, 3)" :key="index">
|
||||
<van-image :src="img" fit="cover" radius="4"></van-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-prod-view" v-else>
|
||||
<van-image :src="item.productImgList[0]" fit="cover" radius="4" class="p-img"></van-image>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-info">
|
||||
<div class="info-row">
|
||||
<span>订单号:</span>
|
||||
<em>{{ item.orderId }}</em>
|
||||
<div class="order-info">
|
||||
<div class="info-row" v-if="item.cashPaid === 1">
|
||||
<span class="payment-warning">积分已支付,待“支付宝/微信/其他”支付</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="(Number(item.orderState) === 6 || Number(item.orderState) === 7) && item.orderMainId">
|
||||
<span class="label">关联发货单号:</span>
|
||||
<span class="value">{{ item.orderMainId }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="Number(item.orderState) === 6 && item.relPointsPrice">
|
||||
<span class="label">原发货单消耗积分:</span>
|
||||
<span class="value points">{{ item.relPointsPrice }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="item.wPayOrAPay">
|
||||
<span class="label">支付宝/微信/其他:</span>
|
||||
<span class="value points">{{ item.wPayOrAPay }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="item.refund">
|
||||
<span class="label">退回积分:</span>
|
||||
<span class="value points">{{ item.refund }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="item.orderNumberId">
|
||||
<span class="label">订单编号:</span>
|
||||
<span class="value">{{ item.orderNumberId }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">订单号:</span>
|
||||
<span class="value">{{ item.orderId }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">消费积分:</span>
|
||||
<span class="value points">{{ item.pointsPrice || 0 }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="item.freightCost">
|
||||
<span class="label">运费:</span>
|
||||
<span class="value">¥ {{ item.freightCost }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">创建时间:</span>
|
||||
<span class="value">{{ item.orderCreateTime || "-" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span>消费积分:</span>
|
||||
<em class="points">{{ item.pointsPrice || 0 }}</em>
|
||||
</div>
|
||||
<div class="info-row" v-if="item.freightCost">
|
||||
<span>运费:</span>
|
||||
<em>¥ {{ item.freightCost }}</em>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span>创建时间:</span>
|
||||
<em>{{ item.orderCreateTime || "-" }}</em>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="card-footer">
|
||||
<van-button v-if="Number(item.orderState) === 4" round size="small" color="#4CAF50" @click.stop="openSupplierOrder(item)">确认收货</van-button>
|
||||
<van-button round size="small" color="#409EFF" @click.stop="openSupplierOrder(item)">查看订单</van-button>
|
||||
</footer>
|
||||
</article>
|
||||
<footer class="card-footer">
|
||||
<div class="order-type"></div>
|
||||
<div class="action-bar">
|
||||
<van-button v-if="Number(item.orderState) === 4" round size="small" color="#4CAF50" @click.stop="userOrderReceive(item)">确认收货</van-button>
|
||||
<van-button round size="small" color="#409EFF" @click.stop="openSupplierOrder(item)">查看订单</van-button>
|
||||
</div>
|
||||
</footer>
|
||||
</article>
|
||||
|
||||
</van-list>
|
||||
<van-empty
|
||||
v-else-if="!tableLoading"
|
||||
class="empty-tip"
|
||||
image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
|
||||
description="暂无订单数据"
|
||||
></van-empty>
|
||||
</van-list>
|
||||
<van-empty
|
||||
v-else-if="!tableLoading"
|
||||
class="empty-tip"
|
||||
image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
|
||||
description="暂无订单数据"
|
||||
></van-empty>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -86,9 +142,21 @@ layout("/layouts/platform_h5.html"){
|
||||
return {
|
||||
userPoints: 0,
|
||||
tableLoading: false,
|
||||
refreshing: false,
|
||||
tableFinished: false,
|
||||
tableData: [],
|
||||
tabList: [],
|
||||
normalTabList: [
|
||||
{ code: -1, name: "全部", class: "gray" },
|
||||
{ code: 0, name: "待付款", class: "orange" },
|
||||
{ code: 2, name: "进行中", class: "blue" },
|
||||
{ code: 3, name: "已取消", class: "gray" },
|
||||
{ code: 4, name: "已妥投", class: "green" },
|
||||
{ code: 5, name: "已完成", class: "gray" }
|
||||
],
|
||||
specialTabList: [
|
||||
{ code: 6, name: "换货", class: "purple" },
|
||||
{ code: 7, name: "退货", class: "red" }
|
||||
],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
@@ -99,10 +167,6 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
methods: {
|
||||
back() { this.$pjaxReplace("/platform/h5/points-mall") },
|
||||
async loadTabs() {
|
||||
const resp = await this.$axios.post("/platform/h5/points-mall/order/stateList")
|
||||
if (resp.code === 0) this.tabList = resp.data || []
|
||||
},
|
||||
async loadPoints() {
|
||||
const resp = await this.$axios.post("/platform/h5/points-mall/me/points")
|
||||
if (resp.code === 0) this.userPoints = resp.data || 0
|
||||
@@ -113,6 +177,11 @@ layout("/layouts/platform_h5.html"){
|
||||
this.tableFinished = false
|
||||
this.pageData()
|
||||
},
|
||||
onTabClick(code) {
|
||||
if (Number(this.pageForm.orderState) === Number(code)) return
|
||||
this.pageForm.orderState = code
|
||||
this.doSearch()
|
||||
},
|
||||
async pageData() {
|
||||
if (this.tableFinished) return
|
||||
this.tableLoading = true
|
||||
@@ -133,6 +202,17 @@ layout("/layouts/platform_h5.html"){
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
},
|
||||
async onRefresh() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.tableData = []
|
||||
this.tableFinished = false
|
||||
try {
|
||||
await this.loadPoints()
|
||||
await this.pageData()
|
||||
} finally {
|
||||
this.refreshing = false
|
||||
}
|
||||
},
|
||||
async openSupplierOrder(item) {
|
||||
const resp = await this.$axios.post("/platform/h5/points-mall/order/supplierOrderUrl", {
|
||||
supplierId: item.supplierId,
|
||||
@@ -143,67 +223,115 @@ layout("/layouts/platform_h5.html"){
|
||||
if (url) window.location.href = url
|
||||
else this.$toast("暂无订单跳转地址")
|
||||
},
|
||||
async userOrderReceive(item) {
|
||||
try {
|
||||
await this.$dialog.confirm({
|
||||
title: "确认收货",
|
||||
message: "您是否确认收货?",
|
||||
cancelButtonText: "取消",
|
||||
confirmButtonText: "确认"
|
||||
})
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
const resp = await this.$axios.post("/platform/h5/points-mall/order/userOrderReceive", {
|
||||
emplid: item.userId,
|
||||
supplierId: item.supplierId,
|
||||
orderId: item.orderId,
|
||||
orderType: item.orderType
|
||||
})
|
||||
if (resp.code !== 0) {
|
||||
this.$toast(resp.msg || "确认收货失败")
|
||||
return
|
||||
}
|
||||
this.$toast.success("确认收货成功")
|
||||
this.loadPoints()
|
||||
this.doSearch()
|
||||
},
|
||||
orderStateName(value) {
|
||||
const item = this.tabList.find((tab) => String(tab.code) === String(value))
|
||||
if (item) return item.name
|
||||
const map = { 0: "待付款", 1: "已支付", 2: "进行中", 3: "已取消", 4: "已签收", 5: "已完成", 6: "换货", 7: "退货" }
|
||||
return map[value] || "未知状态"
|
||||
const item = this.getOrderStatusItem(value)
|
||||
return item ? item.name : "未知状态"
|
||||
},
|
||||
getStatusClass(status) {
|
||||
const value = Number(status)
|
||||
if (value === 0) return "orange"
|
||||
if (value === 1 || value === 2) return "blue"
|
||||
if (value === 4) return "green"
|
||||
if (value === 6) return "purple"
|
||||
if (value === 7) return "red"
|
||||
return "gray"
|
||||
const item = this.getOrderStatusItem(status)
|
||||
return item ? item.class : "gray"
|
||||
},
|
||||
getOrderStatusItem(value) {
|
||||
const list = this.normalTabList.concat(this.specialTabList)
|
||||
return list.find((tab) => Number(tab.code) === Number(value))
|
||||
},
|
||||
getOrderTypeName(orderType) {
|
||||
const typeMap = { 1: "支付单", 2: "发货单" }
|
||||
return typeMap[orderType] || ""
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadTabs()
|
||||
this.loadPoints()
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
body { background: #fbfcff; }
|
||||
.order-page { background: #fbfcff; }
|
||||
.order-header { position: relative; height: 166px; overflow: hidden; background: url("/assets/mobile/img/mall/order/my-order.png") center / cover no-repeat; }
|
||||
.points-content { position: absolute; left: 24px; top: 50px; z-index: 2; }
|
||||
.points-label { color: #111; font-size: 14px; line-height: 20px; }
|
||||
.points-value { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
|
||||
.points-value span { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; color: #fff; background: #ffbf00; font-size: 15px; font-weight: 700; box-shadow: 0 3px 8px rgba(255, 191, 0, .35); }
|
||||
.points-value strong { color: #000; font-size: 28px; line-height: 32px; font-weight: 800; }
|
||||
.filter-bar { display: flex; align-items: center; height: 46px; background: #fff; box-shadow: 0 2px 8px rgba(40, 50, 70, .03); }
|
||||
.custom-tabs { flex: 1; min-width: 0; }
|
||||
.custom-tabs .van-tabs__wrap { height: 46px; }
|
||||
.custom-tabs .van-tab { flex: none; padding: 0 14px; color: #666; font-size: 14px; }
|
||||
.custom-tabs .van-tab--active { color: #1989fa; font-weight: 500; }
|
||||
.custom-tabs .van-tabs__line { bottom: 16px; height: 2px; background: #1989fa; }
|
||||
.list-container { background: #fbfcff; }
|
||||
.order-card { margin: 12px; padding: 16px; border-radius: 12px; background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .04); }
|
||||
.card-header { display: flex; align-items: center; justify-content: space-between; padding-bottom: 12px; border-bottom: 1px solid #f5f5f5; }
|
||||
body { height: 100%; overflow: hidden; background: #f7f8fa; }
|
||||
html { height: 100%; overflow: hidden; }
|
||||
#app { height: 100%; overflow: hidden; }
|
||||
.order-list-page { height: calc(100vh - 46px); padding-bottom: 0; overflow: hidden; background: #f7f8fa; }
|
||||
.order-header { position: relative; height: 160px; overflow: hidden; background: url("/assets/mobile/img/mall/order/my-order.png") center / cover no-repeat; }
|
||||
.points-content { position: absolute; left: 24px; top: 46px; z-index: 2; }
|
||||
.points-label { margin-bottom: 8px; color: #111; font-size: 14px; line-height: 20px; }
|
||||
.points-value { display: flex; align-items: center; color: #333; font-weight: 700; }
|
||||
.points-value span { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-right: 8px; border-radius: 50%; color: #fff; background: #ffc107; font-size: 14px; box-shadow: 0 2px 4px rgba(255, 193, 7, .4); }
|
||||
.points-value strong { color: #000; font-size: 28px; line-height: 32px; font-weight: 800; font-family: "DIN Alternate", Arial, sans-serif; }
|
||||
.filter-bar { display: flex; align-items: center; height: 44px; background: #fff; box-shadow: 0 2px 6px rgba(0, 0, 0, .02); }
|
||||
.grid-icon { flex: none; width: 40px; display: flex; align-items: center; justify-content: center; }
|
||||
.custom-tab-wrap { flex: 1; display: flex; align-items: center; height: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
|
||||
.custom-tab-wrap::-webkit-scrollbar { display: none; }
|
||||
.tab-group { flex: none; display: flex; align-items: center; height: 100%; }
|
||||
.tab-group--normal { background: #eef5ff; }
|
||||
.tab-group--special { background: #fff4ec; }
|
||||
.tab-divider { flex: none; display: flex; align-items: center; align-self: stretch; padding: 0 2px; color: #d0d0d0; background: #fff; font-size: 16px; line-height: 44px; }
|
||||
.tab-item { position: relative; display: flex; align-items: center; height: 100%; padding: 0 12px; color: #666; font-size: 13px; white-space: nowrap; }
|
||||
.tab-item:active { opacity: .7; }
|
||||
.tab-group--normal .tab-item--active { color: #1989fa; font-weight: 700; }
|
||||
.tab-group--special .tab-item--active { color: #e65100; font-weight: 700; }
|
||||
.tab-item--active:after { position: absolute; bottom: 0; left: 50%; width: 20px; height: 2px; border-radius: 2px; content: ""; transform: translateX(-50%); }
|
||||
.tab-group--normal .tab-item--active:after { background: #1989fa; }
|
||||
.tab-group--special .tab-item--active:after { background: #e65100; }
|
||||
.list-container { height: calc(100vh - 46px - 160px - 44px); padding: 12px; overflow-y: auto; background: #f7f8fa; -webkit-overflow-scrolling: touch; box-sizing: border-box; }
|
||||
.order-card { margin-bottom: 12px; padding: 16px; border-radius: 12px; background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .04); }
|
||||
.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid #f5f5f5; }
|
||||
.shop-info { display: flex; align-items: center; min-width: 0; }
|
||||
.shop-name { overflow: hidden; color: #333; font-size: 15px; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }
|
||||
.status-text { flex: none; margin-left: 10px; font-size: 13px; font-weight: 500; }
|
||||
.status-text.orange { color: #ff8a00; }
|
||||
.status-text.blue { color: #1989fa; }
|
||||
.status-text.green { color: #23b65d; }
|
||||
.status-text.purple { color: #7b61ee; }
|
||||
.status-text.red { color: #e64a3b; }
|
||||
.status-text.gray { color: #999; }
|
||||
.product-row { display: flex; gap: 8px; padding: 12px 0; }
|
||||
.product-row .van-image { width: 70px; height: 70px; background: #f3f4f6; }
|
||||
.shop-name { overflow: hidden; margin-right: 4px; color: #333; font-size: 15px; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }
|
||||
.order-type-name { flex: none; margin-left: 4px; color: #666; font-size: 12px; }
|
||||
.status-box { flex: none; display: flex; align-items: center; margin-left: 10px; font-size: 13px; font-weight: 500; }
|
||||
.status-text { display: inline-flex; align-items: center; justify-content: center; min-width: 52px; height: 24px; padding: 0 8px; border-radius: 10px; font-size: 12px; line-height: 24px; box-sizing: border-box; }
|
||||
.status-bg-gray { color: #999; background: #f5f5f5; }
|
||||
.status-bg-green { color: #2e7d32; background: #e8f5e9; }
|
||||
.status-bg-blue { color: #1565c0; background: #e3f2fd; }
|
||||
.status-bg-orange { color: #e65100; background: #fff8e1; }
|
||||
.status-bg-purple { color: #6a1b9a; background: #ede7f6; }
|
||||
.status-bg-red { color: #c62828; background: #fce4ec; }
|
||||
.card-body { margin-bottom: 12px; }
|
||||
.multi-prod-view { display: flex; align-items: center; }
|
||||
.imgs-scroll { flex: 1; display: flex; overflow: hidden; }
|
||||
.img-box { flex: none; width: 70px; height: 70px; margin-right: 8px; background: #f3f4f6; border-radius: 4px; overflow: hidden; }
|
||||
.single-prod-view { display: flex; }
|
||||
.p-img { flex: none; width: 70px; height: 70px; margin-right: 12px; background: #f3f4f6; }
|
||||
.card-body .van-image { width: 70px; height: 70px; display: block; }
|
||||
.order-info { padding: 12px; margin-bottom: 12px; border-radius: 8px; background: #fafafa; }
|
||||
.info-row { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 8px; font-size: 13px; line-height: 18px; }
|
||||
.info-row:last-child { margin-bottom: 0; }
|
||||
.info-row span { flex: none; color: #999; }
|
||||
.info-row span:first-child { flex: none; color: #999; }
|
||||
.info-row .label { flex: none; color: #999; }
|
||||
.info-row .value { min-width: 0; color: #333; text-align: right; word-break: break-all; }
|
||||
.info-row em { min-width: 0; color: #333; font-style: normal; text-align: right; word-break: break-all; }
|
||||
.info-row .points { color: #c62828; font-weight: 700; }
|
||||
.card-footer { display: flex; justify-content: flex-end; gap: 10px; }
|
||||
.card-footer { display: flex; align-items: center; justify-content: space-between; }
|
||||
.order-type { flex: 1; min-width: 0; }
|
||||
.action-bar { display: flex; justify-content: flex-end; gap: 10px; }
|
||||
.card-footer .van-button { min-width: 86px; height: 32px; padding: 0 16px; font-size: 13px; }
|
||||
.empty-tip { padding-top: 36px; }
|
||||
.info-row .payment-warning { color: #e64a3b; font-size: 14px; }
|
||||
</style>
|
||||
<!--#
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user