shish hai 1 mes
pai
achega
26859abb7d
Modificáronse 4 ficheiros con 706 adicións e 2 borrados
  1. 16 2
      hdh5/admin/ghs/pay.vue
  2. 12 0
      hdh5/api/purchase/index.js
  3. 10 0
      hdh5/pages.json
  4. 668 0
      hdh5/pagesPurchase/gathering.vue

+ 16 - 2
hdh5/admin/ghs/pay.vue

@@ -18,8 +18,8 @@
 				</view>
 				<view class="customer-details">
 					<text class="customer-name">{{ customInfo.name || '客户' }}</text>
-					<text class="customer-status" :class="{ 'has-debt': Number(customInfo.remainDebtAmount) > 0 }">
-						{{ Number(customInfo.remainDebtAmount) > 0 ? '待结款' : '账单已结清' }}
+					<text class="customer-status has-debt" @click="goGathering">
+						查看待结订单
 					</text>
 				</view>
 			</view>
@@ -372,6 +372,20 @@ export default {
 			});
 		},
 
+		// 跳转到待结订单页面
+		goGathering() {
+			if (!this.id) {
+				uni.showToast({
+					title: '供货商信息加载中,请稍后再试',
+					icon: 'none'
+				});
+				return;
+			}
+			uni.navigateTo({
+				url: `/pagesPurchase/gathering?id=${this.id}&salt=${this.salt}`
+			});
+		},
+
 
 	}
 }

+ 12 - 0
hdh5/api/purchase/index.js

@@ -6,4 +6,16 @@ export const purchaseAliPay = async data => {
 
 export const purchaseClearAliPay = async data => {
     return https.post("/purchase-clear/ali-pay", data);
+};
+
+export const purchaseDebtList = async data => {
+    return https.get("/purchase/debt-list", data);
+};
+
+export const ghsDetail = async data => {
+    return https.get("/ghs/detail", data);
+};
+
+export const purchaseClearCreateOrder = async data => {
+    return https.post("/purchase-clear/create-order", data);
 };

+ 10 - 0
hdh5/pages.json

@@ -10,6 +10,16 @@
 				}
 			}
 		},
+		{
+			"path": "pagesPurchase/gathering",
+			"style": {
+				"navigationBarTitleText": "待结账单",
+				"navigationStyle": "custom",
+				"h5": {
+					"titleNView": false
+				}
+			}
+		},
 		{
 			"path": "admin/cg/alipay",
 			"style": {

+ 668 - 0
hdh5/pagesPurchase/gathering.vue

@@ -0,0 +1,668 @@
+<template>
+	<view class="gathering-container">
+		<!-- 自定义导航栏 -->
+		<view class="nav-bar">
+			<view class="nav-back" @click="goBack">
+				<text class="back-arrow">&lt;</text>
+			</view>
+			<view class="nav-title">待结账单</view>
+			<view class="nav-placeholder"></view>
+		</view>
+
+		<!-- 头部占位,防止内容被导航栏遮挡 -->
+		<view class="nav-bar-placeholder"></view>
+
+		<!-- 供货商信息 Banner -->
+		<view class="supplier-banner" v-if="ghsInfo.name">
+			<image class="supplier-avatar" :src="ghsInfo.avatar || '/static/default-avatar.png'" mode="aspectFill" />
+			<view class="supplier-details">
+				<text class="supplier-name">{{ ghsInfo.name }}</text>
+				<text class="supplier-desc">请选择需要结清的采购订单</text>
+			</view>
+		</view>
+
+		<!-- 订单列表区域 -->
+		<scroll-view scroll-y class="order-list-scroll">
+			<view class="list-wrapper">
+				<block v-if="detailsList && detailsList.length > 0">
+					<view 
+						v-for="(item, index) in detailsList" 
+						:key="item.id" 
+						class="order-item-card"
+						:class="{ 'item-checked': item.checked }"
+						@click="toggleCheckItem(index)">
+						
+						<!-- 选择框 -->
+						<view class="checkbox-wrapper">
+							<view class="custom-checkbox" :class="{ 'checked': item.checked }">
+								<view class="checkbox-inner" v-if="item.checked"></view>
+							</view>
+						</view>
+
+						<!-- 订单内容 -->
+						<view class="order-content">
+							<view class="order-header">
+								<text class="order-sn">采购单 {{ item.orderSn }}</text>
+								<text class="order-time">{{ formatTime(item.addTime) }}</text>
+							</view>
+							
+							<view class="order-price-info">
+								<view class="price-row">
+									<text class="price-label">待结金额:</text>
+									<text class="price-value">¥{{ parseFloat(item.remainDebtPrice || item.debtPrice || 0).toFixed(2) }}</text>
+								</view>
+								
+								<!-- 部分结清展示 -->
+								<view class="partial-clear-info" v-if="item.showPartialClear">
+									<text class="partial-text">已清 ¥{{ item.hasPayDebt }},原始欠款 ¥{{ parseFloat(item.debtPrice).toFixed(2) }}</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</block>
+
+				<!-- 空状态 -->
+				<view class="empty-state" v-else-if="!loading">
+					<image class="empty-img" src="/static/empty.png" mode="aspectFit" v-if="hasEmptyImg" />
+					<view class="empty-icon" v-else>📝</view>
+					<text class="empty-text">暂无待结订单</text>
+				</view>
+
+				<!-- 加载中 -->
+				<view class="loading-state" v-if="loading">
+					<text class="loading-text">加载中...</text>
+				</view>
+			</view>
+		</scroll-view>
+
+		<!-- 底部结算栏 -->
+		<view class="bottom-action-bar">
+			<view class="select-all-section" @click="toggleSelectAll">
+				<view class="custom-checkbox" :class="{ 'checked': isAllChecked }">
+					<view class="checkbox-inner" v-if="isAllChecked"></view>
+				</view>
+				<text class="select-all-text">{{ isAllChecked ? '全不选' : '全选' }}</text>
+			</view>
+
+			<view class="summary-section">
+				<view class="summary-text">
+					已选 <text class="highlight-count">{{ selectList.length }}</text> 笔
+				</view>
+				<view class="total-amount">
+					合计: <text class="currency-symbol">¥</text><text class="amount-value">{{ selectTotalAmount }}</text>
+				</view>
+			</view>
+
+			<button 
+				class="pay-submit-btn" 
+				:disabled="selectList.length === 0"
+				:class="{ 'btn-disabled': selectList.length === 0 }"
+				@click="batchConfirm">
+				付款结清
+			</button>
+		</view>
+	</view>
+</template>
+
+<script>
+/**
+ * 待结账单页面
+ * 用途:展示花店向供货商采购的待结款订单,支持多选并一键跳转支付宝结账
+ * 谁用:花店端用户
+ */
+import { purchaseDebtList, ghsDetail, purchaseClearCreateOrder, purchaseClearAliPay } from '@/api/purchase/index';
+
+export default {
+	name: 'gathering',
+	data() {
+		return {
+			ghsId: 0,
+			salt: '',
+			ghsInfo: {},
+			detailsList: [],
+			loading: false,
+			hasEmptyImg: false,
+			page: 1,
+			pageSize: 100
+		};
+	},
+	computed: {
+		// 已选订单列表
+		selectList() {
+			return this.detailsList.filter(item => item.checked);
+		},
+		// 已选订单总金额
+		selectTotalAmount() {
+			let total = 0;
+			this.selectList.forEach(item => {
+				total += Number(item.remainDebtPrice || 0);
+			});
+			return total.toFixed(2);
+		},
+		// 是否全选
+		isAllChecked() {
+			if (!this.detailsList || this.detailsList.length === 0) {
+				return false;
+			}
+			return this.selectList.length === this.detailsList.length;
+		}
+	},
+	onLoad(options) {
+		// 解析路由参数 id/salt
+		if (options.id) {
+			this.ghsId = options.id;
+		} else if (options.q) {
+			// 支持小票二维码扫描打开
+			const currentUrl = decodeURIComponent(options.q);
+			const match = currentUrl.match(/[?&]id=(\d+)/);
+			if (match && match[1]) {
+				this.ghsId = match[1];
+			}
+		}
+		
+		if (options.salt) {
+			this.salt = options.salt;
+		}
+
+		if (this.ghsId) {
+			this.loadData();
+		} else {
+			uni.showToast({
+				title: '参数错误,缺少供货商ID',
+				icon: 'none'
+			});
+		}
+	},
+	methods: {
+		// 返回上一页
+		goBack() {
+			uni.navigateBack({
+				delta: 1
+			});
+		},
+		// 格式化时间,截取月-日 时:分
+		formatTime(timeStr) {
+			if (!timeStr) return '';
+			return timeStr.substring(5, 16);
+		},
+		// 加载供货商信息和待结订单列表
+		async loadData() {
+			this.loading = true;
+			uni.showLoading({ title: '加载中...', mask: true });
+			
+			try {
+				// 1. 获取供货商详情
+				const ghsRes = await ghsDetail({ id: this.ghsId, salt: this.salt });
+				if (ghsRes && ghsRes.code === 1) {
+					this.ghsInfo = ghsRes.data;
+				}
+
+				// 2. 获取待结订单列表
+				const listRes = await purchaseDebtList({
+					id: this.ghsId,
+					salt: this.salt,
+					page: this.page,
+					pageSize: this.pageSize
+				});
+
+				uni.hideLoading();
+				this.loading = false;
+
+				if (listRes && listRes.code === 1) {
+					const rawList = listRes.data.list || [];
+					// 映射数据,添加 checked 属性和部分结清判断
+					this.detailsList = rawList.map(item => {
+						const debtPrice = Number(item.debtPrice) || 0;
+						const remainDebtPrice = Number(item.remainDebtPrice) || 0;
+						let hasPayDebt = Number(item.hasPayDebt);
+						if (isNaN(hasPayDebt)) {
+							hasPayDebt = debtPrice > remainDebtPrice ? debtPrice - remainDebtPrice : 0;
+						}
+						return {
+							...item,
+							checked: false,
+							hasPayDebt: hasPayDebt.toFixed(2),
+							showPartialClear: hasPayDebt > 0
+						};
+					});
+				} else {
+					uni.showToast({
+						title: listRes.msg || '获取账单列表失败',
+						icon: 'none'
+					});
+				}
+			} catch (err) {
+				uni.hideLoading();
+				this.loading = false;
+				uni.showToast({
+					title: '请求失败,请检查网络',
+					icon: 'none'
+				});
+			}
+		},
+		// 切换单项选择状态
+		toggleCheckItem(index) {
+			if (this.detailsList[index]) {
+				this.$set(this.detailsList[index], 'checked', !this.detailsList[index].checked);
+			}
+		},
+		// 切换全选/全不选
+		toggleSelectAll() {
+			const targetState = !this.isAllChecked;
+			this.detailsList.forEach((item, index) => {
+				this.$set(this.detailsList[index], 'checked', targetState);
+			});
+		},
+		// 批量付款结清
+		batchConfirm() {
+			if (this.selectList.length === 0) {
+				uni.showToast({
+					title: '请选择订单',
+					icon: 'none'
+				});
+				return;
+			}
+
+			const that = this;
+			uni.showModal({
+				title: '确认提交',
+				content: `确认结清选中的 ${this.selectList.length} 笔订单,合计 ¥${this.selectTotalAmount} 吗?`,
+				success: (res) => {
+					if (res.confirm) {
+						that.submitPayment();
+					}
+				}
+			});
+		},
+		// 提交结账并跳转支付
+		async submitPayment() {
+			uni.showLoading({ title: '正在创建结账单...', mask: true });
+			const purchaseIds = this.selectList.map(item => item.id).join(',');
+
+			try {
+				// 1. 创建结账订单
+				const createRes = await purchaseClearCreateOrder({
+					purchaseIds: purchaseIds,
+					ghsId: this.ghsId
+				});
+
+				if (createRes && createRes.code === 1) {
+					// 2. 获取支付宝支付链接
+					const orderSn = createRes.data.orderSn;
+					uni.showLoading({ title: '正在获取支付链接...', mask: true });
+					
+					const payRes = await purchaseClearAliPay({ orderSn: orderSn });
+					uni.hideLoading();
+
+					if (payRes && payRes.code === 1 && payRes.data.hasRenew === 1) {
+						uni.showToast({
+							title: '正在跳转支付...',
+							icon: 'success',
+							duration: 1500
+						});
+						// 延迟跳转,确保提示框可见
+						setTimeout(() => {
+							window.location.href = payRes.data.payUrl;
+						}, 300);
+					} else {
+						uni.showToast({
+							title: (payRes && payRes.msg) || '商家暂未开通此支付功能',
+							icon: 'none',
+							duration: 2000
+						});
+					}
+				} else {
+					uni.hideLoading();
+					uni.showToast({
+						title: (createRes && createRes.msg) || '创建结账单失败',
+						icon: 'none',
+						duration: 2000
+					});
+				}
+			} catch (err) {
+				uni.hideLoading();
+				uni.showToast({
+					title: '操作失败,请重试',
+					icon: 'none'
+				});
+			}
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.gathering-container {
+	min-height: 100vh;
+	background-color: #f7f8fa;
+	display: flex;
+	flex-direction: column;
+	position: relative;
+	box-sizing: border-box;
+}
+
+/* 自定义导航栏样式 */
+.nav-bar {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	padding: 20upx 30upx;
+	background: #fff;
+	border-bottom: 1upx solid #eef0f2;
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 88upx;
+	z-index: 100;
+	box-sizing: border-box;
+	
+	.nav-back {
+		width: 60upx;
+		height: 60upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		border-radius: 50%;
+		background: #f5f6f8;
+		cursor: pointer;
+		
+		.back-arrow {
+			font-size: 36upx;
+			color: #333;
+			font-weight: bold;
+		}
+	}
+	
+	.nav-title {
+		color: #333;
+		font-size: 34upx;
+		font-weight: 600;
+	}
+	
+	.nav-placeholder {
+		width: 60upx;
+	}
+}
+
+.nav-bar-placeholder {
+	height: 88upx;
+	width: 100%;
+}
+
+/* 供货商 Banner */
+.supplier-banner {
+	display: flex;
+	align-items: center;
+	padding: 30upx;
+	background: linear-gradient(135deg, #3385ff 0%, #5197ff 100%);
+	color: #fff;
+	margin-bottom: 20upx;
+	box-shadow: 0 4upx 12upx rgba(51, 133, 255, 0.2);
+	
+	.supplier-avatar {
+		width: 100upx;
+		height: 100upx;
+		border-radius: 50%;
+		border: 4upx solid rgba(255, 255, 255, 0.6);
+		margin-right: 24upx;
+		background-color: rgba(255, 255, 255, 0.2);
+	}
+	
+	.supplier-details {
+		display: flex;
+		flex-direction: column;
+		
+		.supplier-name {
+			font-size: 34upx;
+			font-weight: 600;
+			margin-bottom: 8upx;
+		}
+		
+		.supplier-desc {
+			font-size: 24upx;
+			color: rgba(255, 255, 255, 0.8);
+		}
+	}
+}
+
+/* 订单列表 */
+.order-list-scroll {
+	flex: 1;
+	height: 0; /* 必须设置,配合 flex: 1 才能在 scroll-view 中正常滚动 */
+}
+
+.list-wrapper {
+	padding: 10upx 24upx 160upx; /* 底部预留空间给结算栏 */
+}
+
+.order-item-card {
+	display: flex;
+	align-items: center;
+	padding: 24upx;
+	background-color: #fff;
+	border-radius: 16upx;
+	margin-bottom: 20upx;
+	box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.02);
+	border: 2upx solid transparent;
+	transition: all 0.2s ease;
+	
+	&.item-checked {
+		border-color: rgba(51, 133, 255, 0.3);
+		background-color: #fcfdff;
+	}
+}
+
+/* 自定义复选框 */
+.checkbox-wrapper {
+	margin-right: 24upx;
+}
+
+.custom-checkbox {
+	width: 40upx;
+	height: 40upx;
+	border: 2upx solid #ccc;
+	border-radius: 50%;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	transition: all 0.2s ease;
+	box-sizing: border-box;
+	
+	&.checked {
+		border-color: #3385ff;
+		background-color: #3385ff;
+	}
+	
+	.checkbox-inner {
+		width: 16upx;
+		height: 16upx;
+		border-radius: 50%;
+		background-color: #fff;
+	}
+}
+
+/* 订单内容 */
+.order-content {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+	
+	.order-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 16upx;
+		
+		.order-sn {
+			font-size: 28upx;
+			font-weight: 600;
+			color: #333;
+		}
+		
+		.order-time {
+			font-size: 24upx;
+			color: #999;
+		}
+	}
+	
+	.order-price-info {
+		display: flex;
+		flex-direction: column;
+		
+		.price-row {
+			display: flex;
+			align-items: baseline;
+			
+			.price-label {
+				font-size: 26upx;
+				color: #666;
+			}
+			
+			.price-value {
+				font-size: 32upx;
+				font-weight: bold;
+				color: #ff4d4f;
+			}
+		}
+		
+		.partial-clear-info {
+			margin-top: 8upx;
+			background-color: #fff1f0;
+			border-radius: 8upx;
+			padding: 8upx 16upx;
+			display: inline-block;
+			align-self: flex-start;
+			
+			.partial-text {
+				font-size: 22upx;
+				color: #ff4d4f;
+				font-weight: 500;
+			}
+		}
+	}
+}
+
+/* 状态样式 */
+.empty-state {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	padding: 120upx 0;
+	
+	.empty-icon {
+		font-size: 80upx;
+		margin-bottom: 20upx;
+	}
+	
+	.empty-text {
+		font-size: 28upx;
+		color: #999;
+	}
+}
+
+.loading-state {
+	text-align: center;
+	padding: 40upx 0;
+	
+	.loading-text {
+		font-size: 26upx;
+		color: #999;
+	}
+}
+
+/* 底部结算栏 */
+.bottom-action-bar {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	height: 120upx;
+	background-color: #fff;
+	box-shadow: 0 -4upx 16upx rgba(0, 0, 0, 0.05);
+	display: flex;
+	align-items: center;
+	padding: 0 30upx;
+	box-sizing: border-box;
+	z-index: 90;
+	
+	.select-all-section {
+		display: flex;
+		align-items: center;
+		cursor: pointer;
+		margin-right: 30upx;
+		
+		.select-all-text {
+			font-size: 28upx;
+			color: #333;
+			margin-left: 12upx;
+			font-weight: 500;
+		}
+	}
+	
+	.summary-section {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		
+		.summary-text {
+			font-size: 22upx;
+			color: #666;
+			margin-bottom: 4upx;
+			
+			.highlight-count {
+				color: #3385ff;
+				font-weight: bold;
+				margin: 0 4upx;
+			}
+		}
+		
+		.total-amount {
+			font-size: 26upx;
+			color: #333;
+			font-weight: 500;
+			
+			.currency-symbol {
+				color: #ff4d4f;
+				font-size: 24upx;
+				margin-left: 6upx;
+			}
+			
+			.amount-value {
+				color: #ff4d4f;
+				font-size: 36upx;
+				font-weight: bold;
+			}
+		}
+	}
+	
+	.pay-submit-btn {
+		width: 220upx;
+		height: 80upx;
+		line-height: 80upx;
+		background: linear-gradient(135deg, #3385ff 0%, #1e70eb 100%);
+		color: #fff;
+		font-size: 30upx;
+		font-weight: bold;
+		border-radius: 40upx;
+		border: none;
+		box-shadow: 0 4upx 12upx rgba(30, 112, 235, 0.3);
+		transition: all 0.2s ease;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		
+		&:active {
+			transform: scale(0.97);
+		}
+		
+		&.btn-disabled {
+			background: #e1e4e8 !important;
+			color: #969faf !important;
+			box-shadow: none !important;
+		}
+	}
+}
+</style>