From 2eb21bfe2f40630a46e675211f23b5f240e395a4 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期五, 12 九月 2025 15:01:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/user_action' into send_coupon

---
 pages.json                                 |   19 ++
 pages/order/claim-coupon/claim-coupon.vue  |  350 +++++++++++++++++++++++++++++++++++++++++++
 api/coupon.js                              |   74 +++++++++
 pages/commodity-square/commoditySquare.vue |    2 
 4 files changed, 442 insertions(+), 3 deletions(-)

diff --git a/api/coupon.js b/api/coupon.js
new file mode 100644
index 0000000..6721566
--- /dev/null
+++ b/api/coupon.js
@@ -0,0 +1,74 @@
+
+
+import { http, Method } from "@/utils/request.js";
+
+/**
+ * 鑾峰彇铏氭嫙鍟嗗搧浼樻儬鍒稿垪琛�
+ * @param {Object} params - 鏌ヨ鍙傛暟
+ * @param {number} params.pageNumber - 椤电爜
+ * @param {number} params.pageSize - 姣忛〉鏁伴噺
+ * @param {string} params.claimStatus - 棰嗗彇鐘舵�� (NOT_CLAIM: 鏈鍙�, CLAIM: 宸查鍙�)
+ * @param {string} params.userId - 鐢ㄦ埛ID
+ * @param {string} params.orderId - 璁㈠崟ID
+ * @returns {Promise} 杩斿洖浼樻儬鍒稿垪琛�
+ */
+export function getVirtualCoupons(params) {
+  return http.request({
+    url: "/lmk/coupon/virtual",
+    method: Method.GET,
+    needToken: true,
+    params,
+  });
+}
+
+/**
+ * 棰嗗彇铏氭嫙鍟嗗搧浼樻儬鍒�
+ * @param {string|number} id - 浼樻儬鍒窱D
+ * @returns {Promise} 杩斿洖棰嗗彇缁撴灉
+ */
+export function claimVirtualCoupon(id) {
+  return http.request({
+    url: `/lmk/coupon/card/${id}`,
+    method: Method.POST,
+    needToken: true,
+  });
+}
+
+/**
+ * 鏍规嵁璁㈠崟ID鑾峰彇铏氭嫙鍟嗗搧浼樻儬鍒�
+ * @param {string} orderId - 璁㈠崟ID
+ * @returns {Promise} 杩斿洖浼樻儬鍒稿垪琛�
+ */
+export function getVirtualCouponsByOrderId(orderId) {
+  return http.request({
+    url: `/lmk/coupon/virtual/order/${orderId}`,
+    method: Method.GET,
+    needToken: true,
+  });
+}
+
+/**
+ * 鏍规嵁浼樻儬鍗烽鍙朓D鑾峰彇铏氭嫙鍟嗗搧浼樻儬鍒�
+ * @param {string} userId - 鐢ㄦ埛ID
+ * @returns {Promise} 杩斿洖浼樻儬鍒稿垪琛�
+ */
+export function getVirtualCouponsByUserId(userId) {
+  return http.request({
+    url: `/lmk/coupon/card/couponCardInfo/${userId}`,
+    method: Method.GET,
+    needToken: true,
+  });
+}
+
+/**
+ * 鑾峰彇浼樻儬鍒歌鎯�
+ * @param {string|number} id - 浼樻儬鍒窱D
+ * @returns {Promise} 杩斿洖浼樻儬鍒歌鎯�
+ */
+export function getVirtualCouponDetail(id) {
+  return http.request({
+    url: `/lmk/coupon/card/couponCardInfo/${id}`,
+    method: Method.POST,
+    needToken: true,
+  });
+}
\ No newline at end of file
diff --git a/pages.json b/pages.json
index 861b104..4a7378d 100644
--- a/pages.json
+++ b/pages.json
@@ -1779,8 +1779,23 @@
           }
         },
         {
+        	"path" : "claim-coupon/claim-coupon",
+        	"style" :
+        	{
+        		"navigationBarTitleText" : "浼樻儬鍒搁鍙�",
+        		"enablePullDownRefresh" : true,
+				"componentPlaceholder": {
+				  "u-image": "view",
+				  "u-tag": "view",
+				  "u-loading": "view",
+				  "u-empty": "view",
+				  "u-modal":"view"
+				}
+        	}
+        },
+        {
         	"path" : "editOrderAddress/editOrderAddress",
-        	"style" : 
+        	"style" :
         	{
         		"navigationBarTitleText" : "淇敼璁㈠崟",
 				"componentPlaceholder": {
@@ -1796,7 +1811,7 @@
         },
         {
         	"path" : "cardPack",
-        	"style" : 
+        	"style" :
         	{
         		"navigationBarTitleText" : "浼樻儬鍔靛崱鍖�",
 				"componentPlaceholder": {
diff --git a/pages/commodity-square/commoditySquare.vue b/pages/commodity-square/commoditySquare.vue
index 85e0b28..ec242c5 100644
--- a/pages/commodity-square/commoditySquare.vue
+++ b/pages/commodity-square/commoditySquare.vue
@@ -51,7 +51,7 @@
 							<view class="goodsContent" style="font-size: 24rpx;">
 								{{item.sellingPoint}}
 							</view>
-							<view
+							<view v-if="item.goodsType !=='VIRTUAL_GOODS'"
 								style="display: flex; justify-content: space-between;align-items:center; 100%;width: 100%;">
 								<view class="goodsPrice">锟{item.price}}</view>
 								<view class="addCard" style="display: flex; align-items: center;">
diff --git a/pages/order/claim-coupon/claim-coupon.vue b/pages/order/claim-coupon/claim-coupon.vue
new file mode 100644
index 0000000..2acfa09
--- /dev/null
+++ b/pages/order/claim-coupon/claim-coupon.vue
@@ -0,0 +1,350 @@
+<template>
+	<view class="container">
+		<!-- 椤堕儴鏍囬 -->
+		<view class="header">
+			<text class="title">浼樻儬鍒搁鍙�</text>
+			<text class="subtitle">棰嗗彇鎮ㄧ殑涓撳睘浼樻儬鍒�</text>
+		</view>
+		
+		<!-- 鍗曚釜浼樻儬鍒稿睍绀� -->
+		<view class="coupon-container" v-if="couponInfo">
+			<view class="coupon-card">
+				<!-- 鍟嗗搧鍥剧墖 -->
+				<view class="goods-image-container">
+					<u-image 
+						:src="couponInfo.goodsImage || '/static/default_goods.png'" 
+						width="100%" 
+						height="300rpx" 
+						mode="aspectFit"
+						border-radius="16"
+						@click="previewImage(couponInfo.goodsImage)"
+					></u-image>
+				</view>
+				
+				<!-- 浼樻儬鍒镐俊鎭� -->
+				<view class="coupon-info">
+					<view class="coupon-name">{{ couponInfo.couponName || couponInfo.name }}</view>
+					<view class="goods-name">{{ couponInfo.skuName }}</view>
+					<view class="coupon-no">缂栧彿锛歿{ couponInfo.couponNo }}</view>
+					<view class="time-info">
+						<text class="create-time">鍒涘缓鏃堕棿锛歿{ formatDate(couponInfo.createTime) }}</text>
+					</view>
+					<view class="status">
+						<u-tag 
+							:text="couponInfo.claimStatus === 'CLAIM' ? '宸查鍙�' : '鏈鍙�'" 
+							:type="couponInfo.claimStatus === 'CLAIM' ? 'success' : 'warning'" 
+							size="mini"
+						/>
+					</view>
+				</view>
+				
+				<!-- 棰嗗彇鎸夐挳 -->
+				<view class="claim-btn-container">
+					<button 
+						class="claim-btn" 
+						:class="{ 'claimed': couponInfo.claimStatus === 'CLAIM' }"
+						:disabled="couponInfo.claimStatus === 'CLAIM'"
+						@click="claimCoupon"
+					>
+						{{ couponInfo.claimStatus === 'CLAIM' ? '宸查鍙�' : '绔嬪嵆棰嗗彇' }}
+					</button>
+				</view>
+			</view>
+		</view>
+		
+		<!-- 鍔犺浇涓姸鎬� -->
+		<view class="loading-container" v-else-if="loading">
+			<u-loading mode="circle" size="40"></u-loading>
+			<text class="loading-text">鍔犺浇涓�...</text>
+		</view>
+		
+		<!-- 绌虹姸鎬� -->
+		<u-empty 
+			v-else 
+			text="鏆傛棤浼樻儬鍒�" 
+			mode="coupon" 
+			icon-size="120"
+			margin-top="200"
+		></u-empty>
+		
+		<!-- 鍘昏喘鐗╁脊绐� -->
+		<u-modal 
+			v-model="showShoppingModal" 
+			:content="'鎭枩鎮ㄩ鍙栨垚鍔燂紝鏄惁绔嬪嵆浣跨敤浼樻儬鍒稿幓璐墿锛�'"
+			:show-cancel-button="true"
+			confirm-text="鍘昏喘鐗�"
+			cancel-text="绋嶅悗鍐嶈"
+			@confirm="goShopping"
+			@cancel="closeModal"
+		></u-modal>
+	</view>
+</template>
+
+<script>
+	import { getVirtualCouponDetail, claimVirtualCoupon } from '@/api/coupon.js';
+	
+	export default {
+		data() {
+			return {
+				couponInfo: null, // 鍗曚釜浼樻儬鍒镐俊鎭�
+				loading: false,
+				showShoppingModal: false ,// 鎺у埗鍘昏喘鐗╁脊绐楁樉绀�
+				couponId:''
+			}
+		},
+		onLoad(options) {
+			// 閫氳繃鍙傛暟浼犻�掍紭鎯犲埜ID
+			// 渚嬪: /pages/order/claim-coupon/claim-coupon?id=123
+			options.id = '1966390012058017794'
+			
+			this.couponId = ''
+			if (options.id) {
+				this.loadCouponInfo(options.id);
+			} else {
+				// 濡傛灉娌℃湁浼犻�扞D锛屾樉绀虹┖鐘舵��
+				uni.showToast({
+					title: '缂哄皯浼樻儬鍒窱D鍙傛暟',
+					icon: 'none'
+				});
+			}
+		},
+		methods: {
+			// 鍔犺浇鎸囧畾ID鐨勪紭鎯犲埜淇℃伅
+			async loadCouponInfo(id) {
+				if (this.loading) return;
+				this.loading = true;
+				
+				try {
+					// 璋冪敤鑾峰彇鍗曚釜浼樻儬鍒歌鎯呯殑鎺ュ彛
+					const res = await getVirtualCouponDetail(id);
+					
+					if (res.data.code===200) {
+						this.couponInfo = res.data.data;
+					} else {
+						throw new Error(res.message || '鑾峰彇浼樻儬鍒稿け璐�');
+					}
+				} catch (err) {
+					console.error('鑾峰彇浼樻儬鍒镐俊鎭け璐�:', err);
+					uni.showToast({
+						title: err.message || '鑾峰彇浼樻儬鍒稿け璐�',
+						icon: 'none'
+					});
+				} finally {
+					this.loading = false;
+				}
+			},
+			
+			// 棰嗗彇浼樻儬鍒�
+			async claimCoupon() {
+				if (!this.couponInfo || this.couponInfo.claimStatus === 'CLAIM') {
+					uni.showToast({
+						title: '璇ヤ紭鎯犲埜宸查鍙�',
+						icon: 'none'
+					});
+					return;
+				}
+				
+				try {
+					uni.showLoading({
+						title: '棰嗗彇涓�...'
+					});
+					
+					// 璋冪敤棰嗗彇浼樻儬鍒告帴鍙�
+					const res = await claimVirtualCoupon(this.couponInfo.id);
+					
+					if (res.data.code===200) {
+						// 鏇存柊鏈湴鐘舵��
+						this.couponId = res.data.data
+						this.$set(this.couponInfo, 'claimStatus', 'CLAIM');
+						this.$set(this.couponInfo, 'claimTime', new Date());
+						uni.hideLoading();
+						uni.showToast({
+							title: '棰嗗彇鎴愬姛',
+							icon: 'success'
+						});
+						
+						// 鏄剧ず鍘昏喘鐗╁脊绐�
+						this.showShoppingModal = true;
+					} else {
+						throw new Error(res.message || '棰嗗彇澶辫触');
+					}
+				} catch (err) {
+					uni.hideLoading();
+					console.error('棰嗗彇浼樻儬鍒稿け璐�:', err);
+					uni.showToast({
+						title: err.message || '棰嗗彇澶辫触',
+						icon: 'none'
+					});
+				}
+			},
+			
+			// 鍘昏喘鐗�
+			goShopping() {
+				// 鍏抽棴寮圭獥
+				this.showShoppingModal = false;
+				
+				// 杩欓噷鍙互娣诲姞璺宠浆鍒拌喘鐗╅〉闈㈢殑閫昏緫
+				// 渚嬪璺宠浆鍒板晢鍝佽鎯呴〉鎴栬喘鐗╄溅椤甸潰
+				// 鏍规嵁瀹為檯闇�姹傝皟鏁磋烦杞矾寰�
+				if (this.couponInfo && this.couponInfo.skuId) {
+					// 濡傛灉鏈夊晢鍝両D锛岃烦杞埌鍟嗗搧璇︽儏椤�
+					uni.navigateTo({
+						url: `/pages/commodity-square/coups-goods-list?promotionsId=${this.couponId}&promotionType=COUPON`
+					});
+				} else {
+					// 鍚﹀垯璺宠浆鍒伴椤垫垨鍏朵粬椤甸潰
+					uni.switchTab({
+						url: '/pages/tabbar/index/home'
+					});
+				}
+			},
+			
+			// 鍏抽棴寮圭獥
+			closeModal() {
+				this.showShoppingModal = false;
+				// 鍏抽棴寮圭獥鍚庤繑鍥炰笂涓�椤�
+				uni.navigateBack();
+			},
+			
+			// 鏍煎紡鍖栨棩鏈�
+			formatDate(date) {
+				if (!date) return '';
+				const d = new Date(date);
+				return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
+			},
+			
+			// 棰勮鍥剧墖
+			previewImage(url) {
+				if (url) {
+					uni.previewImage({
+						urls: [url]
+					});
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	padding: 20rpx;
+	background-color: #f5f5f5;
+	min-height: 100vh;
+}
+
+.header {
+	background-color: #fff;
+	padding: 30rpx;
+	border-radius: 16rpx;
+	margin-bottom: 20rpx;
+	text-align: center;
+	
+	.title {
+		font-size: 36rpx;
+		font-weight: bold;
+		color: #333;
+		display: block;
+		margin-bottom: 10rpx;
+	}
+	
+	.subtitle {
+		font-size: 28rpx;
+		color: #999;
+	}
+}
+
+.coupon-container {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	min-height: 60vh;
+}
+
+.coupon-card {
+	background-color: #fff;
+	border-radius: 16rpx;
+	padding: 30rpx;
+	width: 90%;
+	box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+	text-align: center;
+	
+	.goods-image-container {
+		margin-bottom: 30rpx;
+		border-radius: 16rpx;
+		overflow: hidden;
+	}
+	
+	.coupon-info {
+		margin-bottom: 30rpx;
+		
+		.coupon-name {
+			font-size: 36rpx;
+			font-weight: bold;
+			color: #333;
+			margin-bottom: 20rpx;
+		}
+		
+		.goods-name {
+			font-size: 30rpx;
+			color: #666;
+			margin-bottom: 20rpx;
+			line-height: 1.5;
+		}
+		
+		.coupon-no {
+			font-size: 26rpx;
+			color: #999;
+			margin-bottom: 20rpx;
+		}
+		
+		.time-info {
+			font-size: 26rpx;
+			color: #999;
+			margin-bottom: 20rpx;
+		}
+		
+		.status {
+			margin-bottom: 20rpx;
+		}
+	}
+	
+	.claim-btn-container {
+		.claim-btn {
+			width: 80%;
+			height: 80rpx;
+			background-color: #ff6b6b;
+			color: #fff;
+			border-radius: 40rpx;
+			font-size: 32rpx;
+			border: none;
+			margin: 0 auto;
+			
+			&:active {
+				background-color: #ff5252;
+			}
+			
+			&.claimed {
+				background-color: #ccc;
+			}
+			
+			&[disabled] {
+				background-color: #ccc;
+			}
+		}
+	}
+}
+
+.loading-container {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	height: 60vh;
+	
+	.loading-text {
+		margin-top: 20rpx;
+		color: #999;
+		font-size: 28rpx;
+	}
+}
+</style>
\ No newline at end of file

--
Gitblit v1.8.0