shish 23 ore în urmă
părinte
comite
f3ab0340f0
1 a modificat fișierele cu 305 adăugiri și 183 ștergeri
  1. 305 183
      mallApp/src/pages/balance/changeList.vue

+ 305 - 183
mallApp/src/pages/balance/changeList.vue

@@ -1,184 +1,306 @@
+<!--
+  商城客户充值余额变动明细
+  用途:我的余额进入;读 xhBalancePayChange;排版对齐 ghsApp 账单式列表
+-->
 <template>
-    <view class="app-content">
-            <block v-if="!$util.isEmpty(list.data)">
-                <view class="balance-table">
-                    <view class="table-header table-row">
-                        <view class="table-cell cell-date">日期</view>
-                        <view class="table-cell cell-event">事项</view>
-                        <view class="table-cell cell-staff">操作</view>
-                        <view class="table-cell cell-amount">变动</view>
-                        <view class="table-cell cell-balance">余额</view>
-                    </view>
-                    <view v-for="(item, index) in list.data" :key="index" class="table-body">
-                        <view class="table-row table-row-data" @click="goDetail(item)">
-                            <view class="table-cell cell-date">{{ item.addTime.substr(5,11) }}</view>
-                            <view class="table-cell cell-event">{{ item.event }}</view>
-                            <view class="table-cell cell-staff">{{ item.staffName }}</view>
-                            <view class="table-cell cell-amount">{{ item.amount }}</view>
-                            <view class="table-cell cell-balance">{{ parseFloat(item.balance) }}</view>
-                        </view>
-                        <view class="table-row table-row-extra" v-if="Number(item.settleId)>0 || !$util.isEmpty(item.remark) || Number(item.refundOrderId)>0 || Number(item.shOrderId)>0">
-                            <view class="table-cell cell-extra" :colspan="5">
-                                <view v-if="Number(item.settleId)>0">结账单 {{item.settleNo}} {{item.settleAmount?parseFloat(item.settleAmount):0}}元</view>
-                                
-                                <view v-if="Number(item.settleAmount)>0 && Number(item.becomeBalance)>0">余额 {{item.becomeBalance}}元</view>
-                                
-                                <view v-if="Number(item.shOrderId)>0" @click.stop="goShPayOrder(item)">售后付款单{{ item.shOrderSn }}</view>
-
-                                <view v-if="Number(item.refundOrderId)>0" @click.stop="goRefundOrder(item)">订单 {{ item.refundOrderSn }}</view>
-
-                                <view v-if="!$util.isEmpty(item.remark)">{{ item.remark }}</view>
-                            </view>
-                        </view>
-                    </view>
-                </view>
-            </block>
-            <block v-else>
-                <AppWrapperEmpty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
-            </block>
-        </view>
-    </template>
-    <script>
-    import AppWrapperEmpty from "@/components/app-wrapper-empty";
-    import { getBalanceChangeList, getBalancePayChangeDetail } from '@/api/custom'
-    import list from '@/mixins/list'
-    export default {
-        name: "balanceChange",
-        components: {
-            AppWrapperEmpty
-        },
-        mixins:[list],
-        data() {
-            return {
-            };
-        },
-        methods: {
-            goDetail(item){
-                if(item.capitalType == 0){
-                    //订单详情
-                    this.$util.pageTo({url: '/pages/order/detail?id='+item.relateId})
-                }
-                if(item.capitalType == 59){
-                    //售后单和售后记录还没有开发
-                }
-            },
-            goShPayOrder(item){
-                this.$util.pageTo({ url: '/pages/order/detail?id='+item.shOrderId})
-            },
-            goRefundOrder(item){
-                this.$util.pageTo({ url: '/pages/order/detail?id='+item.refundOrderId})
-            },
-            async init(){
-                let hdId = this.option.hdId ? this.option.hdId : 0
-                const res = await getBalancePayChangeDetail({ page:this.list.page, hdId:hdId})
-                if (this.$util.isEmpty(res.data.list)){
-                    this.completes(res)
-                    return
-                }
-                let currentList = res.data.list
-
-                currentList.forEach(function(item,index,array){
-                    array[index].amount = item.io == 0 ? '-'+parseFloat(item.amount) : '+'+parseFloat(item.amount)
-                });
-
-                res.data.list = currentList
-                this.completes(res)
-            }
-        },
-        async onPullDownRefresh() {
-            this.resetList();
-            await this.init()
-            uni.stopPullDownRefresh();
-        },
-        async onReachBottom() {
-            if (!this.list.finished) {
-                await this.init()
-                uni.stopPullDownRefresh();;
-            } else {
-                uni.stopPullDownRefresh();
-            }
-        }
-    };
-    </script>
-    <style lang="scss" scoped>
-    .balance-table {
-        width: 100%;
-        border-radius: 16upx;
-        overflow: hidden;
-        background: #fff;
-        box-shadow: 0 4upx 24upx rgba(0,0,0,0.06);
-        margin: 20upx 0;
-        .table-row {
-            display: flex;
-            align-items: center;
-            min-height: 72upx;
-            border-bottom: 1px solid #f0f0f0;
-            &.table-header {
-                background: #f5f7fa;
-                font-weight: bold;
-                font-size: 30upx;
-                color: #333;
-            }
-            &.table-row-data {
-                font-size: 26upx;
-                color: #222;
-                transition: background 0.2s;
-                cursor: pointer;
-                &:hover {
-                    background: #f0f9ff;
-                }
-            }
-            &.table-row-remark {
-                background: #fafbfc;
-                color: #989494;
-                font-size: 24upx;
-                .cell-remark {
-                    padding: 16upx 20upx;
-                }
-            }
-            &.table-row-extra {
-                background: #f8f8f8;
-                color: #989494;
-                font-size: 24upx;
-                .cell-extra {
-                    padding: 16upx 20upx;
-                    display: flex;
-                    flex-direction: column;
-                    gap: 2upx;
-                }
-            }
-        }
-        .table-cell {
-            flex: 1;
-            padding: 18upx 8upx 18upx 8upx;
-            &.cell-date {
-                text-align: center;
-                min-width: 100upx;
-                flex: 1.2;
-            }
-            &.cell-staff {
-                text-align: center;
-                min-width: 60upx;
-                flex: 0.8;
-            }
-            &.cell-event {
-                text-align: left;
-                min-width: 200upx;
-                flex: 2.2;
-            }
-            &.cell-amount {
-                text-align: right;
-                min-width: 100upx;
-                font-weight: 500;
-                flex: 1;
-            }
-            &.cell-balance {
-                text-align: right;
-                min-width: 100upx;
-                font-weight: 500;
-                padding-right: 32upx;
-                flex: 1;
-            }
-        }
-    }
-    </style>
+	<view class="bc-page">
+		<view v-if="hasList" class="bc-sheet">
+			<view
+				v-for="(item, index) in list.data"
+				:key="index"
+				class="bc-item"
+				@click="goDetail(item)"
+			>
+				<view class="bc-main">
+					<text class="bc-event">{{ item.event }}</text>
+					<text class="bc-amount" :class="item.amountClassName">{{ item.amount }}</text>
+				</view>
+				<view class="bc-sub">
+					<view class="bc-sub-left">
+						<text class="bc-time">{{ item.dateText }} {{ item.timeLine }}</text>
+						<text v-if="item.showStaff" class="bc-staff">{{ item.staffName }}</text>
+					</view>
+					<text class="bc-balance">余额 {{ item.balanceText }}</text>
+				</view>
+				<text v-if="item.showRemark" class="bc-remark">{{ item.remark }}</text>
+				<view v-if="item.showExtraRow" class="bc-extra" @click.stop>
+					<text
+						v-if="item.showSettleLink"
+						class="bc-tag bc-tag--muted"
+					>{{ item.settleLinkText }}</text>
+					<text
+						v-if="item.showBecomeBalance"
+						class="bc-tag bc-tag--muted"
+					>{{ item.becomeBalanceText }}</text>
+					<text
+						v-if="item.showShOrderLink"
+						class="bc-tag"
+						@click.stop="goShPayOrder(item)"
+					>{{ item.shOrderLinkText }}</text>
+					<text
+						v-if="item.showRefundLink"
+						class="bc-tag"
+						@click.stop="goRefundOrder(item)"
+					>{{ item.refundLinkText }}</text>
+				</view>
+			</view>
+		</view>
+		<AppWrapperEmpty v-else title="暂无数据" :is-empty="listEmpty" />
+	</view>
+</template>
+<script>
+/**
+ * mallApp 余额变动:读充值本金流水;账单式排版对齐 ghs balanceChange
+ * 订单跳转必须带 account/hdId,否则详情页店铺上下文丢失
+ */
+import AppWrapperEmpty from '@/components/app-wrapper-empty'
+import { getBalancePayChangeDetail } from '@/api/custom'
+import list from '@/mixins/list'
+
+export default {
+	name: 'balanceChangeList',
+	components: {
+		AppWrapperEmpty
+	},
+	mixins: [list],
+	computed: {
+		hasList() {
+			return this.list.data && this.list.data.length > 0
+		},
+		listEmpty() {
+			return !this.hasList
+		}
+	},
+	methods: {
+		formatMoney(val) {
+			const n = parseFloat(val)
+			return isNaN(n) ? '0' : String(n)
+		},
+		hasText(val) {
+			return val !== undefined && val !== null && String(val).trim() !== ''
+		},
+		/**
+		 * 拼订单详情地址:mall 详情依赖 account(店铺)与 hdId
+		 * 优先用流水行上的 shopId/hdId,缺省回退页面入参
+		 */
+		buildOrderDetailUrl(orderId, item) {
+			const account = (item && item.shopId) || (this.option && this.option.account) || 0
+			const hdId = (item && item.hdId) || (this.option && this.option.hdId) || 0
+			return '/pages/order/detail?id=' + orderId + '&account=' + account + '&hdId=' + hdId
+		},
+		/** 列表行展示字段:金额颜色、时间、结账/售后外链 */
+		mapListItem(item, amountDisplay) {
+			const row = Object.assign({}, item)
+			row.amount = amountDisplay
+			const text = String(amountDisplay || '')
+			row.amountClassName = (text.indexOf('+') === 0 || Number(row.io) === 1) ? 'bc-amount--in' : 'bc-amount--out'
+			const addTime = row.addTime || ''
+			if (addTime.length >= 16) {
+				row.dateText = addTime.substr(5, 5)
+				row.timeLine = addTime.substr(11, 5)
+			} else if (addTime.length >= 11) {
+				row.dateText = addTime.substr(0, 10)
+				row.timeLine = addTime.substr(11)
+			} else {
+				row.dateText = addTime
+				row.timeLine = ''
+			}
+			row.balanceText = this.formatMoney(row.balance)
+			row.showSettleLink = Number(row.settleId) > 0
+			row.settleLinkText = '结账单 ' + (row.settleNo || '') + ' · ' + this.formatMoney(row.settleAmount) + '元'
+			row.showBecomeBalance = Number(row.settleAmount) > 0 && Number(row.becomeBalance) > 0
+			row.becomeBalanceText = '余额 ' + this.formatMoney(row.becomeBalance) + '元'
+			row.showShOrderLink = Number(row.shOrderId) > 0
+			row.shOrderLinkText = '售后付款单 ' + (row.shOrderSn || '')
+			row.showRefundLink = Number(row.refundOrderId) > 0
+			row.refundLinkText = '订单 ' + (row.refundOrderSn || '')
+			row.showStaff = this.hasText(row.staffName)
+			row.showRemark = this.hasText(row.remark)
+			row.showExtraRow = row.showSettleLink || row.showBecomeBalance || row.showShOrderLink || row.showRefundLink
+			return row
+		},
+		async init() {
+			const hdId = this.option.hdId ? this.option.hdId : 0
+			const res = await getBalancePayChangeDetail({ page: this.list.page, hdId: hdId })
+			if (this.$util.isEmpty(res.data.list)) {
+				this.completes(res)
+				return
+			}
+			const rows = []
+			res.data.list.forEach((item) => {
+				const amountDisplay = item.io == 0 ? '-' + parseFloat(item.amount) : '+' + parseFloat(item.amount)
+				rows.push(this.mapListItem(item, amountDisplay))
+			})
+			res.data.list = rows
+			this.completes(res)
+		},
+		goDetail(item) {
+			// capitalType 0:销售订单;59:售后单 → 售后详情
+			if (item.capitalType == 0 && Number(item.relateId) > 0) {
+				this.$util.pageTo({ url: this.buildOrderDetailUrl(item.relateId, item) })
+				return
+			}
+			if (item.capitalType == 59 && Number(item.relateId) > 0) {
+				this.$util.pageTo({ url: '/pages/order/refund-detail?id=' + item.relateId })
+			}
+		},
+		goShPayOrder(item) {
+			this.$util.pageTo({ url: this.buildOrderDetailUrl(item.shOrderId, item) })
+		},
+		/** 「订单 xxx」标签:refundOrderId 是原销售单 id,不是售后申请 id */
+		goRefundOrder(item) {
+			this.$util.pageTo({ url: this.buildOrderDetailUrl(item.refundOrderId, item) })
+		}
+	},
+	async onPullDownRefresh() {
+		this.resetList()
+		await this.init()
+		uni.stopPullDownRefresh()
+	},
+	async onReachBottom() {
+		if (!this.list.finished) {
+			await this.init()
+		}
+		uni.stopPullDownRefresh()
+	}
+}
+</script>
+<style lang="scss" scoped>
+.bc-page {
+	min-height: 100vh;
+	background: #fff;
+	box-sizing: border-box;
+}
+
+.bc-sheet {
+	width: 100%;
+	background: #fff;
+}
+
+.bc-item {
+	padding: 28upx 28upx 24upx;
+	border-bottom: 1upx solid #f0f1f3;
+	box-sizing: border-box;
+}
+
+.bc-item:last-child {
+	border-bottom: none;
+}
+
+.bc-item:active {
+	background: #f7f8fa;
+}
+
+.bc-main {
+	display: flex;
+	flex-direction: row;
+	align-items: flex-start;
+	justify-content: space-between;
+}
+
+.bc-event {
+	flex: 1;
+	min-width: 0;
+	margin-right: 24upx;
+	font-size: 30upx;
+	color: #1a1a1a;
+	font-weight: 500;
+	line-height: 1.4;
+	word-break: break-all;
+}
+
+.bc-amount {
+	flex-shrink: 0;
+	font-size: 32upx;
+	font-weight: 600;
+	line-height: 1.3;
+	font-variant-numeric: tabular-nums;
+}
+
+.bc-amount--in {
+	color: #07a84c;
+}
+
+.bc-amount--out {
+	color: #e62e45;
+}
+
+.bc-sub {
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+	justify-content: space-between;
+	margin-top: 10upx;
+}
+
+.bc-sub-left {
+	flex: 1;
+	min-width: 0;
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+	margin-right: 16upx;
+}
+
+.bc-time {
+	flex-shrink: 0;
+	font-size: 28upx;
+	color: #999;
+	line-height: 1.4;
+}
+
+.bc-staff {
+	flex: 1;
+	min-width: 0;
+	margin-left: 12upx;
+	font-size: 28upx;
+	color: #999;
+	line-height: 1.4;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+.bc-balance {
+	flex-shrink: 0;
+	font-size: 28upx;
+	color: #999;
+	line-height: 1.4;
+	font-variant-numeric: tabular-nums;
+}
+
+.bc-remark {
+	display: block;
+	margin-top: 8upx;
+	font-size: 22upx;
+	color: #b3b3b3;
+	line-height: 1.4;
+	word-break: break-all;
+}
+
+.bc-extra {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	margin-top: 16upx;
+}
+
+.bc-tag {
+	max-width: 100%;
+	padding: 6upx 14upx;
+	margin-right: 12upx;
+	margin-bottom: 8upx;
+	font-size: 28upx;
+	line-height: 1.4;
+	color: #5b8def;
+	background: #eef4ff;
+	border-radius: 8upx;
+	word-break: break-all;
+	box-sizing: border-box;
+}
+
+.bc-tag--muted {
+	color: #969aa0;
+	background: #f3f4f6;
+}
+</style>