Jelajahi Sumber

完成订单部分 逻辑

XSXS 2 minggu lalu
induk
melakukan
36229feaa9

+ 7 - 0
pages.json

@@ -528,6 +528,13 @@
 				"navigationBarTitleText" : "项目历史详情",
 				"navigationStyle": "custom"
 			}
+		},
+		{
+			"path" : "pages/my/creativeExpert",
+			"style" : 
+			{
+				"navigationBarTitleText" : ""
+			}
 		}
 	],
 	"globalStyle": {

+ 58 - 30
pages/crowdFunding/addressEdit.vue

@@ -3,12 +3,7 @@
     <view class="form-card">
       <view class="form-row" v-for="item in formList" :key="item.key">
         <text class="label">{{ item.label }}</text>
-        <input
-          v-if="item.key !== 'region'"
-          class="input"
-          :placeholder="item.placeholder"
-          v-model="form[item.key]"
-        />
+        <input v-if="item.key !== 'region'" class="input" :placeholder="item.placeholder" v-model="form[item.key]" />
         <view v-else class="input region-input" @click="openPicker()">
           <text :class="{ placeholder: !regionText }">
             {{ regionText || "请选择省/市/区" }}
@@ -18,20 +13,14 @@
       <view class="form-row " style="display: flex;align-items: center; justify-content: space-between;">
         <text class="label">设为默认地址</text>
         <uv-switch activeColor="#acf934" inactiveColor="#eee" v-model="form.isDefault" size="28"></uv-switch>
-      
+
       </view>
     </view>
     <view class="save-btn" @click="save">保存</view>
-    <uv-picker
-      ref="picker"
-      :columns="addressList" 
-      keyName="name" 
-      @change="change"
-      @confirm="confirm"
-    />
+    <uv-picker ref="picker" :columns="addressList" keyName="name" @change="change" @confirm="confirm" />
   </view>
 </template>
-  
+
 <script>
 import addressData from "@/static/address/province.json";
 export default {
@@ -45,6 +34,7 @@ export default {
         detail: "",
         zipcode: "",
         isDefault: false,
+        id: "",
       },
       formList: [
         { key: "name", label: "收货人", placeholder: "填写收货人姓名" },
@@ -56,12 +46,12 @@ export default {
           placeholder: "填写详细地址和门牌号",
         },
         { key: "zipcode", label: "邮政编码", placeholder: "填写邮政编码" },
-      ], 
+      ],
       pickerValue: [0, 0, 0],
       provinces: [],
       citys: [],
       areas: [],
-      regionText: "", 
+      regionText: "",
     };
   },
   computed: {
@@ -74,16 +64,42 @@ export default {
     },
   },
   onLoad(options) {
-    this.initAddressData();  
-    
+    this.initAddressData();
+
     if (options.id) {
       this.isEdit = true;
-      uni.setNavigationBarTitle({ title: "编辑地址" }); 
+      uni.setNavigationBarTitle({ title: "编辑地址" });
+      this.getAddressDetail(options.id);
+      this.id = options.id;
     } else {
       uni.setNavigationBarTitle({ title: "添加新地址" });
     }
   },
   methods: {
+    getAddressDetail(id) {
+      uni.request({
+        url: this.$apiHost + '/Address/getinfo?id=' + id,
+        method: 'GET',
+        data: {
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey
+        },
+        success: (res) => {
+          if (res.data  ) {
+            const info = res.data.info;
+            this.form = {
+              name: info.realname || '',
+              mobile: info.mobile || '',
+              region: info.area || '',
+              detail: info.address || '',
+              zipcode: info.postcode || '',
+              isDefault: info.is_default === 'yes'
+            };
+            this.regionText = info.area || '';
+          }
+        }
+      });
+    },
     openPicker() {
       this.$refs.picker.open();
     },
@@ -116,11 +132,11 @@ export default {
       // }
       // this.form.zipcode = zipcode;
       this.showPicker = false;
-       
+
     },
     // 校验方法
     validateForm() {
-      console.log(this.form ,"填写的数据");
+      console.log(this.form, "填写的数据");
       // 姓名
       if (!this.form.name.trim()) {
         uni.showToast({ title: "请填写收货人姓名", icon: "none" });
@@ -158,9 +174,11 @@ export default {
         area: this.form.region.trim(),
         address: this.form.detail.trim(),
         is_default: this.form.isDefault ? 'yes' : 'no',
+        id:this.id,
         uuid: getApp().globalData.uuid,
-					skey: getApp().globalData.skey,
       };
+      console.log(params,"提交的参数");
+      
       // 保存逻辑
       uni.request({
         url: this.$apiHost + '/Address/submitaddress',
@@ -184,34 +202,39 @@ export default {
   },
 };
 </script>
-  
+
 <style lang="scss">
-page{
+page {
   background: #f2f6f2;
 }
+
 .address-edit-page {
   min-height: 100vh;
   background: #f2f6f2;
-  ::v-deep .uni-input-placeholder{
+
+  ::v-deep .uni-input-placeholder {
     color: #bbb !important;
   }
- 
+
   .form-card {
     background: #fff;
     border-radius: 18rpx;
     margin: 32rpx;
-    padding: 32rpx 0; 
+    padding: 32rpx 0;
+
     .form-row {
       display: flex;
       align-items: center;
       border-bottom: 1rpx solid #f2f6f2;
       padding: 24rpx 32rpx;
+
       .label {
         width: 180rpx;
         font-size: 28rpx;
-        color: #222;  
-     
+        color: #222;
+
       }
+
       .input {
         flex: 1;
         font-size: 28rpx;
@@ -219,14 +242,17 @@ page{
         border: none;
         background: transparent;
       }
+
       switch {
         margin-left: auto;
       }
     }
+
     .form-row:last-child {
       border-bottom: none;
     }
   }
+
   .save-btn {
     width: 80vw;
     height: 88rpx;
@@ -239,12 +265,14 @@ page{
     font-size: 32rpx;
     font-weight: bold;
   }
+
   .region-input {
     min-height: 48rpx;
     line-height: 48rpx;
     color: #222;
     border-bottom: 1rpx solid #eee;
     padding: 0 16rpx;
+
     .placeholder {
       color: #bbb;
     }

+ 20 - 12
pages/crowdFunding/crowdfundingDetails.vue

@@ -74,18 +74,20 @@
 					</view>
 				</view>
 				<view class="project-update-right scale-tap"
-					@click="goPage('/pages/crowdFunding/discussionArea?tags=update&id=' +  projectId)">
+					@click="goPage('/pages/crowdFunding/discussionArea?tags=update&id=' + projectId)">
 					<view>历史更新</view>
 					<image src="@/static/crowdFunding/updateDetails.png"></image>
 
 				</view>
 			</view>
 
-			<view class="section comment scale-tap"  @click="goPage('/pages/crowdFunding/discussionArea?tags=comment&id=' + projectId)" >
+			<view class="section comment scale-tap"
+				@click="goPage('/pages/crowdFunding/discussionArea?tags=comment&id=' + projectId)">
 				<view class="comment-title">
 					<view>项目讨论({{ totalNumberOfComments }})</view>
 					<view class="comment-more"">查看更多
-						<image src="@/static/crowdFunding/right.png"></image>
+						<image src=" @/static/crowdFunding/right.png">
+						</image>
 					</view>
 				</view>
 				<view class="comment-content">
@@ -114,7 +116,7 @@
 						<text class="initiator-tag">发起人</text>
 					</view>
 					<view class="initiator-service-btn  blick-btn-animation"
-						@click="goPage('/pages/crowdFunding/customerService?id=' + detail.creator_id)">
+						@click="goPage('/pages/crowdFunding/customerService?id=' + detail.creator_id + '&zc_id=' + detail.id)">
 						<image class="service-icon" src="@/static/crowdFunding/service.png" />
 						<text>客服</text>
 					</view>
@@ -189,7 +191,7 @@ export default {
 			mediaList: [],
 			videoPlaying: false,
 			currentMediaIndex: 0,
-			commentList: [ 
+			commentList: [
 			],
 			navBgOpacity: 0,
 			swiperHeight: 0,
@@ -202,8 +204,8 @@ export default {
 			projectId: null, // 当前项目id
 			detail: {}, // 众筹详情
 			projectUpdate: '',
-			rewards: [], 
-			totalNumberOfComments:0
+			rewards: [],
+			totalNumberOfComments: 0
 		}
 	},
 	computed: {
@@ -272,14 +274,20 @@ export default {
 			});
 		},
 		onSpecConfirm(selectedSpec) {
-			console.log('selectedSpec', selectedSpec);
+			uni.navigateTo({
+				url: '/pages/crowdFunding/orderConfirm',
+				success: function(res) {
+					// 通过 eventChannel 向被打开页面传送数据
+					res.eventChannel.emit('acceptDataFromOpener', { selectedSpec: selectedSpec, detail: this.detail });
+				}.bind(this)
+			});
 		},
 		specificationsOpen() {
 			this.$refs.specSheet.show();
 		},
 		toggleFavorite() {
 			if (!this.projectId) {
-				 
+
 				return;
 			}
 			const action = this.isFavorite ? 'remove' : 'add';
@@ -365,7 +373,7 @@ export default {
 						}
 					}
 				}
-			}); 
+			});
 			uni.request({
 				url: this.$apiHost + '/Article/getcomments',
 				data: {
@@ -381,7 +389,7 @@ export default {
 				},
 				success: (res) => {
 					console.log("评论列表:", res.data);
-					if (res.data.success == "yes") { 
+					if (res.data.success == "yes") {
 						this.totalNumberOfComments = res.data.total
 						// 确保数据存在且是数组,然后只取前两条
 						this.commentList = (res.data.list || []).slice(0, 2).map(item => ({
@@ -390,7 +398,7 @@ export default {
 							likeNum: item.like_count || 0,
 							liked: item.is_like || false
 						}));
-						
+
 					} else {
 						// 如果请求失败,使用默认空数组
 						this.commentList = [];

+ 1148 - 0
pages/crowdFunding/customerService copy.vue

@@ -0,0 +1,1148 @@
+<template>
+	<view class="customer-service-page">
+		<!-- 顶部栏 -->
+		<!-- 顶部导航栏 -->
+		<view class="custom-navbar">
+			<view class="navbar-left">
+				<text class="fa fa-angle-left" @click="goBack"></text>
+				<view class="navbar-title one-omit">
+					时间是一种解药时间是一种解药时间是一种解药时间是一种解药时间是一种解药
+				</view>
+			</view>
+
+			<view class="navbar-right" @click="toggleDropdown">
+				<image src="@/static/icon/more2.png" style="width: 64rpx; height: 64rpx; margin-top: 15rpx"
+					mode="widthFix"></image>
+
+				<view class="dropdown-menu" v-if="showDropdown">
+					<view class="dropdown-item" @tap="handleOption('report')">举报内容</view>
+				</view>
+
+			</view>
+		</view>
+
+		<!-- 聊天内容区 -->
+		<scroll-view class="cs-chat-list" :scroll-y="true" :scroll-with-animation="true"
+			:scroll-into-view="scrollToView" :style="{
+				paddingBottom: (keyboardHeight ? keyboardHeight + 100 : 100) + 'rpx',
+			}">
+			<view v-for="(msg, idx) in chatList" :key="msg.id">
+				<view v-if="shouldShowTime(idx)" class="cs-time-bar">
+					<view class="cs-time-inner">{{ formatTime(msg.time) }}</view>
+				</view>
+				<template v-if="msg.message_type == 5">
+					<view class="cs-msg-order-card-box">
+						<image class="order-card-avatar" :src="msg.avatar" />
+						<view class="cs-msg-order-card">
+							<image class="order-card-img" v-if="msg.order.main_image" :src="msg.order.main_image" mode="aspectFill" />
+							<view class="order-card-info">
+								<view class="order-card-title">{{ msg.order.title }}</view>
+								<view class="order-card-row" v-if="msg.order.orderNo">
+									<text class="order-card-label">订单编号</text>
+									<text class="order-card-value">{{ msg.order.orderNo  }}</text>
+								</view>
+								<view class="order-card-row" v-if="msg.order.orderTime">
+									<text class="order-card-label">下单时间</text>
+									<text class="order-card-value">{{
+										msg.order.orderTime
+									}}</text>
+								</view>
+								<view class="order-card-btn-box">
+									<button class="order-card-btn" @click="goDetails( msg.order)">查看详情</button>
+								</view>
+							</view>
+						</view>
+					</view>
+				</template>
+				<template v-else>
+					<view :id="'msg-' + msg.id" :class="[
+						'cs-msg-item',
+						msg.type === 'user' ? 'cs-msg-self' : 'cs-msg-other',
+					]">
+						<image class="cs-avatar" :src="msg.avatar" />
+						<view class="cs-msg-bubble">
+							<!-- 文本消息 -->
+							<template v-if="msg.message_type === 1">
+								{{ msg.content }}
+							</template>
+							<!-- 图片消息 -->
+							<template v-else-if="msg.message_type === 2">
+								<view style="position:relative;display:inline-block;">
+									<image :src="msg.media_url" mode="widthFix"
+										style="max-width: 180rpx;  border-radius: 8rpx;"
+										@tap="!msg.uploading && previewImage(msg.media_url)" />
+									<view v-if="msg.uploading"
+										style="position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(255,255,255,0.7);display:flex;align-items:center;justify-content:center;">
+										<text style="color:#a6e22e;font-size:24rpx;">{{ msg.progress || 0 }}%</text>
+									</view>
+								</view>
+							</template>
+							<!-- 语音消息 -->
+							<template v-else-if="msg.message_type === 3">
+								<view class="cs-msg-voice">[语音消息] <text style="color:#a6e22e">(暂不支持播放)</text></view>
+							</template>
+							<!-- 视频消息 -->
+							<template v-else-if="msg.message_type === 4">
+								<video :src="msg.media_url" controls
+									style="max-width: 220rpx; max-height: 180rpx; border-radius: 8rpx;" />
+							</template>
+
+							<!-- 其它未知类型 -->
+							<template v-else>
+								<text style="color:#bbb">[未知消息类型]</text>
+							</template>
+						</view>
+					</view>
+				</template>
+			</view>
+			<view style="height: 200rpx; width: 100%"></view>
+			<view :id="'bottom-anchor'"></view>
+			<view v-if="adShow" :style="{ height: orderCardHeight + 'rpx' }"></view>
+		</scroll-view>
+
+		<!-- 底部输入栏 -->
+		<view class="cs-input-bar" :style="{ bottom: keyboardHeight + 'rpx' }">
+			<!-- 广告条 -->
+			<view class="order-card" v-if="adShow">
+				<view class="order-card-header">
+					<image class="order-card-img" :src=" orderCardData.main_image " mode="aspectFill" />
+					<view class="order-card-info">
+						<view class="order-card-title one-omit">{{ orderCardData.title }}</view>
+						<view class="order-card-btn-box">
+							<button class="order-card-btn" @click="sendOrderCardMsg()">
+								发给客服
+							</button>
+						</view>
+					</view>
+					<image class="order-card-close" @click="closeOrderCard" src="@/static/icon/wd_icon_guanbi.png"
+						mode="widthFix"></image>
+				</view>
+				<view class="order-card-row" v-if="orderCardData.orderNo">
+					<text class="order-card-label">订单编号</text>
+					<text class="order-card-value">{{ orderCardData.orderNo }}</text>
+				</view>
+				<view class="order-card-row" v-if="orderCardData.orderTime">
+					<text class="order-card-label">下单时间</text>
+					<text class="order-card-value">{{ orderCardData.orderTime }}</text>
+				</view>
+			</view>
+
+			<!-- 假输入框 -->
+			<view v-if="!showRealInput" class="fake-input-bar" @click="showInputAndFocus">
+				<view class="fake-input-placeholder">在这里输入新消息</view>
+				<view class="fake-input-icons">
+					<image src="/static/icon/icon-picture.png" class="fake-input-icon" />
+					<image src="/static/icon/icon-expression.png" class="fake-input-icon" />
+				</view>
+			</view>
+
+			<!-- 真输入框 -->
+			<view v-else class="cs-input-area">
+				<textarea class="cs-textarea" v-model="inputValue" placeholder="在这里输入新消息" :focus="inputFocused"
+					:adjust-position="false" @focus="onInputFocus" @blur="onInputBlur"
+					@keyboardheightchange="onKeyboardHeightChange" maxlength="300" auto-height
+					:style="{ 'max-height': '120rpx', 'overflow-y': 'auto' }"></textarea>
+				<view class="bottom-bar">
+					<view>
+						<image @tap="upload" src="/static/icon/icon-picture.png" class="fake-input-icon" />
+						<image @tap="toggleEmojiPanel" src="/static/icon/icon-expression.png" class="fake-input-icon" />
+					</view>
+					<view :class="['send_btn', inputValue.trim() ? '' : 'prohibit']" @tap="sendMsg(1)">发送</view>
+				</view>
+			</view>
+		</view>
+
+		<view class="emoji-panel" :class="{ show: showEmojiPanel }" v-if="showEmojiPanel">
+			<view class="emoji-mask" @click="showEmojiPanel = false"></view>
+			<view class="emoji-grid">
+				<view class="emoji-item" v-for="(emoji, index) in emojiList" :key="index" @tap="selectEmoji(emoji)">
+					{{ emoji }}
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import permission from '@/common/permission.js';
+
+export default {
+	data() {
+		return {
+			chatList: [],
+			inputValue: "",
+			pollTimer: null,
+			scrollToView: "bottom-anchor",
+			adShow: true,
+			keyboardHeight: 0,
+			inputFocused: false,
+			orderCardHeight: 260,
+			showEmojiPanel: false,
+			showDropdown: false,
+			emojiList: ["😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", "😙", "😚", "🙂", "🤗", "🤩", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯", "😪", "😫", "🥱", "😴", "😌", "😛", "😜", "😝", "🤤", "😒", "😓", "😔", "😕", "🙃", "🤑", "😲", "☹️", "🙁", "😖", "😞", "😟", "😤", "😢", "😭", "😦", "😧", "😨", "😩", "🤯", "😬", "😰", "😱", "🥵", "🥶", "😳", "🤪", "😵", "😡", "😠", "🤬", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😇", "🥳", "🥺", "🤠", "😈", "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "💩", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾", "🙈", "🙉", "🙊", "💋", "💌", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️", "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍", "💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👋", "🤚", "🖐️", "✋", "🖖", "👌", "🤏", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍", "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦶", "👂", "👃", "🧠", "🦷", "🦴", "��", "👁️", "👅", "👄"],
+			conversationId: 0,
+			creatorId: 0,
+			zcId: 0,
+			lastMsgId: 0,
+			pageSize: 20,
+			userInfo: {},
+			showRealInput: false, // 控制显示真输入框还是假输入框
+			orderCardData: {},
+		};
+	},
+	onLoad(options) {
+		this.creatorId = options.id || 0;
+		this.zcId = options.zc_id || 0;
+		this.fetchMessages();
+		this.startPolling();
+		this.getOrderCardData()
+	},
+	onHide() {
+		this.clearPolling();
+	},
+	onUnload() {
+		this.clearPolling();
+	},
+	methods: {
+		goBack() {
+			uni.navigateBack();
+		},
+		// 轮询获取消息
+		startPolling() {
+			this.clearPolling();
+			this.pollTimer = setInterval(() => this.fetchMessages(false), 5000);
+			this.fetchMessages(false);
+		},
+		clearPolling() {
+			if (this.pollTimer) {
+				clearInterval(this.pollTimer);
+				this.pollTimer = null;
+			}
+		},
+		// 获取消息
+		fetchMessages(isAppend = false) {
+			uni.request({
+				url: this.$apiHost + '/App/kefuGetMessages',
+				method: 'GET',
+				data: {
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+					creator_id: this.creatorId,
+					conversation_id: this.conversationId,
+					last_id: isAppend ? this.lastMsgId : 0,
+					page_size: this.pageSize,
+					zc_id: this.zcId
+				},
+				success: (res) => {
+					if (res.data && res.data.success === 'yes' && res.data.data) {
+						const { messages, conversation, user_info } = res.data.data;
+						this.userInfo = user_info || {};
+						this.conversationId = conversation?.id || 0;
+						// 格式化消息,保留 message_type、media_url 等字段
+						const msgList = (messages || []).map(msg => {
+							let returnValue= {
+								id: msg.id,
+								content: msg.content,
+								type: msg.from_type === 1 ? 'user' : 'customerService',
+								avatar: msg.from_type === 1 ? (user_info.avatar || '/static/makedetail/characterProfilePicture.png') : '/static/home/avator.png',
+								time: msg.create_time,
+								message_type: msg.message_type, // 消息类型
+								media_url: msg.media_url, // 媒体文件URL
+								progress: msg.progress,
+								uploading: msg.uploading
+							}
+							if (msg.message_type == 5) {
+								returnValue.order = JSON.parse(msg.content);
+							}
+							return returnValue;
+						});
+						console.log(msgList, "消息列表");
+						// 合并未上传完成的临时消息
+						const tempMsgs = this.chatList.filter(m => m.uploading);
+						let newList;
+						if (isAppend) {
+							newList = [...msgList, ...this.chatList.filter(m => !m.uploading), ...tempMsgs];
+						} else {
+							newList = [...msgList, ...tempMsgs];
+						}
+						this.chatList = newList;
+						// 记录最后一条消息ID
+						if (messages && messages.length > 0) {
+							this.lastMsgId = messages[0].id;
+						}
+						this.$nextTick(() => {
+							this.scrollToView = "bottom-anchor";
+						});
+					} else {
+						// 只保留临时消息
+						this.chatList = this.chatList.filter(m => m.uploading);
+					}
+				},
+				fail: () => {
+					// 只保留临时消息
+					this.chatList = this.chatList.filter(m => m.uploading);
+				}
+			});
+		},
+		// 发送消息
+		sendMsg(message_type ) {
+
+			if (!this.inputValue.trim() && message_type == 1) return;
+			const content = this.inputValue;
+			this.inputValue = "";
+			console.log(content, "发送消息",message_type);
+			
+			uni.request({
+				url: this.$apiHost + '/App/kefuSendMessage',
+				method: 'POST',
+				header: {
+					"content-type": "application/x-www-form-urlencoded",
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+				},
+				data: {
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+					creator_id: this.creatorId,
+					conversation_id: this.conversationId,
+					message_type: message_type, // 文本
+					content: content,
+					zc_id: this.zcId
+				},
+				success: (res) => {
+					if (res.data && res.data.success === 'yes') {
+						// 发送成功后刷新消息
+						this.fetchMessages(false);
+					} else {
+						uni.showToast({ title: res.data.str || '发送失败', icon: 'none' });
+					}
+				},
+				fail: () => {
+					uni.showToast({ title: '网络错误', icon: 'none' });
+				}
+			});
+		},
+		closeOrderCard() {
+			this.adShow = false;
+		},
+		shouldShowTime(idx) {
+			if (idx === 0) return true;
+			// 找到上一个显示时间条的消息
+			let lastShowIdx = -1;
+			for (let i = idx - 1; i >= 0; i--) {
+				if (this.shouldShowTime(i)) {
+					lastShowIdx = i;
+					break;
+				}
+			}
+			if (lastShowIdx === -1) return true;
+			const curTime = new Date(
+				this.chatList[idx].time.replace(/-/g, "/")
+			).getTime();
+			const lastTime = new Date(
+				this.chatList[lastShowIdx].time.replace(/-/g, "/")
+			).getTime();
+			// 20分钟 = 20*60*1000 毫秒
+			return curTime - lastTime > 20 * 60 * 1000;
+		},
+		formatTime(timeStr) {
+			// 例:'2025-05-21 20:01' => '05月21日 20:01'
+			if (!timeStr) return "";
+			const d = new Date(timeStr.replace(/-/g, "/"));
+			const MM = String(d.getMonth() + 1).padStart(2, "0");
+			const DD = String(d.getDate()).padStart(2, "0");
+			const hhmm = timeStr.slice(11, 16);
+			return `${MM}月${DD}日 ${hhmm}`;
+		},
+		onInputFocus(e) {
+			this.inputFocused = true;
+		},
+		onInputBlur(e) {
+			this.inputFocused = false;
+			this.keyboardHeight = 0;
+		},
+		px2rpx(px) {
+			// 以750设计稿为例,1rpx = 屏幕宽度/750
+			const screenWidth = uni.getSystemInfoSync().windowWidth;
+			return (px * 750) / screenWidth;
+		},
+		onKeyboardHeightChange(e) {
+			let pxHeight = e.detail ? e.detail.height : e.height || 0;
+			// #ifdef H5 || APP-PLUS
+			this.keyboardHeight = this.px2rpx(pxHeight);
+			// #endif
+			// #ifdef MP-WEIXIN
+			this.keyboardHeight = pxHeight; // 小程序下直接用rpx
+			// #endif
+		},
+		toggleEmojiPanel() {
+			this.inputFocused = false;
+			setTimeout(() => {
+				this.showEmojiPanel = !this.showEmojiPanel;
+			}, 100);
+		},
+		selectEmoji(emoji) {
+			this.inputValue += emoji;
+			this.showEmojiPanel = false;
+		},
+		sendOrderCardMsg() {
+			this.chatList.push({
+				id: Date.now(),
+				message_type: 5,
+				avatar: this.avatar, // 用户头像
+				order: {
+					img: "/static/crowdFunding/top-img.png",
+					title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系",
+					orderNo: "12201544521215415415415",
+					orderTime: "2025-05-27 09:35:30",
+				},
+				time: this.getNowTime(),
+			});
+			this.sendMsg(5);
+
+
+			this.$nextTick(() => {
+				this.closeOrderCard();
+				setTimeout(() => {
+					this.scrollToView = "bottom-anchor";
+				}, 1000);
+			});
+		},
+		getNowTime() {
+			const d = new Date();
+			const pad = (n) => (n < 10 ? "0" + n : n);
+			return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(
+				d.getDate()
+			)} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
+		},
+		// 切换下拉菜单显示状态
+		toggleDropdown() {
+			this.showDropdown = !this.showDropdown;
+		},
+		// 处理下拉菜单选项点击
+		handleOption(type) {
+			this.showDropdown = false;
+			switch (type) {
+				case 'report':
+					uni.navigateTo({
+						url: '/pages/my/feedback?isReportContent=true'
+					});
+					break;
+			}
+		},
+		showInputAndFocus() {
+			this.showRealInput = true;
+			this.$nextTick(() => {
+				this.inputFocused = true;
+			});
+		},
+		// 上传图片并发送图片消息,增加进度展示
+		async upload() {
+			uni.showActionSheet({
+				itemList: ['拍照', '从相册选择'],
+				success: async (res) => {
+					const sourceType = res.tapIndex === 0 ? 'camera' : 'album';
+					let hasPermission = false;
+
+					try {
+						if (sourceType === 'camera') {
+							hasPermission = await permission.request(permission.PermissionType.CAMERA, {
+								title: '“萌创星球”想访问你的相机',
+								describe: '萌创星球想访问您的摄像头,便于拍摄获取图片来与其他用户进行交流'
+							});
+						} else {
+							hasPermission = await permission.request(permission.PermissionType.PHOTO_LIBRARY, {
+								title: '“萌创星球”想访问你的照片图库',
+								describe: '萌创星球想访问您本地照片图库,便于获取图片来与其他用户进行交流'
+							});
+						}
+						if (!hasPermission) {
+							uni.showToast({
+								title: sourceType === 'camera' ? '未获得相机权限' : '未获得相册权限',
+								icon: 'none'
+							});
+							return;
+						}
+						// 权限通过后,选择图片
+						uni.chooseImage({
+							count: 1,
+							sizeType: ['compressed'],
+							sourceType: [sourceType],
+							success: (res) => {
+								const filePath = res.tempFilePaths[0];
+								// 1. 先插入临时消息
+								const tempMsgId = 'temp_' + Date.now();
+								this.chatList.push({
+									id: tempMsgId,
+									type: 'user',
+									avatar: this.userInfo.avatar || '/static/makedetail/characterProfilePicture.png',
+									time: this.getNowTime(),
+									message_type: 2,
+									media_url: filePath,
+									progress: 0,
+									uploading: true
+								});
+								this.$nextTick(() => {
+									this.scrollToView = "bottom-anchor";
+								});
+								// 2. 上传图片
+								uni.uploadFile({
+									url: this.$apiHost + '/Xweb/upload_img?skey=' + getApp().globalData.skey,
+									filePath: filePath,
+									name: 'file',
+									// 上传进度
+									progress: (e) => {
+										const idx = this.chatList.findIndex(m => m.id === tempMsgId);
+										if (idx !== -1) this.$set(this.chatList, idx, { ...this.chatList[idx], progress: e.progress });
+									},
+									success: (uploadFileRes) => {
+										let resdata = JSON.parse(uploadFileRes.data);
+										const idx = this.chatList.findIndex(m => m.id === tempMsgId);
+										if (resdata.success == 'no') {
+											if (idx !== -1) this.chatList.splice(idx, 1);
+											uni.showToast({ title: resdata.str, icon: 'none' });
+											return;
+										}
+										if (resdata.code == 0) {
+											// 替换为正式消息
+											if (idx !== -1) this.$set(this.chatList, idx, {
+												id: Date.now(),
+												type: 'user',
+												avatar: this.userInfo.avatar || '/static/makedetail/characterProfilePicture.png',
+												time: this.getNowTime(),
+												message_type: 2,
+												media_url: resdata.data.path,
+												progress: 100,
+												uploading: false
+											});
+											// 发送图片消息到服务端
+											this.sendImageMsg(resdata.data.path);
+										}
+									},
+									fail: () => {
+										const idx = this.chatList.findIndex(m => m.id === tempMsgId);
+										if (idx !== -1) this.chatList.splice(idx, 1);
+										uni.showToast({ title: '图片上传失败', icon: 'none' });
+									}
+								});
+							}
+						});
+					} catch (error) {
+						uni.showToast({
+							title: '权限检查失败',
+							icon: 'none'
+						});
+					}
+				}
+			});
+		},
+		sendImageMsg(imgUrl) {
+			uni.request({
+				url: this.$apiHost + '/App/kefuSendMessage',
+				method: 'POST',
+				header: {
+					"content-type": "application/x-www-form-urlencoded",
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+				},
+				data: {
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey,
+					creator_id: this.creatorId,
+					conversation_id: this.conversationId,
+					message_type: 2, // 2为图片
+					content: '', // 图片消息content可为空
+					media_url: imgUrl, // 图片地址
+					zc_id: this.zcId
+				},
+				success: (res) => {
+					if (res.data && res.data.success === 'yes') {
+						this.fetchMessages(false);
+					} else {
+						uni.showToast({ title: res.data.str || '发送失败', icon: 'none' });
+					}
+				},
+				fail: () => {
+					uni.showToast({ title: '网络错误', icon: 'none' });
+				}
+			});
+		},
+		goDetails(item) {
+			console.log(item,'item');
+			let url = '';
+			if (item.orderNo) {
+				url='/pages/crowdFunding/orderDetails?id=' + item.orderNo;
+			}else{
+				url='/pages/crowdFunding/crowdfundingDetails?id=' + item.id;
+			}
+			uni.navigateTo({
+				url: url
+			});
+		},
+		getOrderCardData() {
+			if (this.zcId) { 
+				uni.request({
+					url: this.$apiHost + '/crowdfund/detail',
+					method: 'GET',
+					data: {
+						id: this.zcId,
+						uuid: getApp().globalData.uuid,
+						skey: getApp().globalData.skey
+						
+					},
+					success: (res) => {
+						if (res.data && res.data.success === 'yes' && res.data.data) {
+							this.orderCardData = res.data.data; 
+							console.log(this.orderCardData,'this.orderCardData');
+							// 可根据接口返回字段设置isFavorite等
+						}
+					}
+				});
+			}
+		},
+		// 图片预览
+		previewImage(url) {
+			// 收集当前消息列表中的所有图片URL
+			const imageUrls = this.chatList
+				.filter(msg => msg.message_type === 2 && msg.media_url)
+				.map(msg => msg.media_url);
+			const currentIndex = imageUrls.indexOf(url);
+			uni.previewImage({
+				current: currentIndex >= 0 ? currentIndex : 0,
+				urls: imageUrls
+			});
+		},
+	},
+};
+</script>
+
+<style lang="scss">
+.customer-service-page {
+	min-height: 100vh;
+	background: #f2f6f2;
+	display: flex;
+	flex-direction: column;
+	position: relative;
+
+	.custom-navbar {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+		height: 90rpx;
+		padding: 0 20rpx;
+		padding-top: var(--status-bar-height);
+		background-color: #ffffff;
+		position: sticky;
+		top: 0;
+		height: calc(90rpx + var(--status-bar-height));
+		z-index: 100;
+
+		.navbar-left {
+			height: 80rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+
+			.fa-angle-left {
+				font-size: 48rpx;
+				color: #333;
+			}
+
+			.navbar-title {
+				max-width: 450rpx;
+				font-family: "PingFang SC-Bold";
+				font-weight: 400;
+				font-size: 32rpx;
+				color: #1f1f1f;
+				padding-left: 20rpx;
+			}
+		}
+
+		.navbar-right {
+			width: 80rpx;
+			height: 80rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+
+			.fa-ellipsis-h {
+				font-size: 36rpx;
+				color: #333;
+			}
+		}
+	}
+
+	.cs-chat-list {
+		flex: 1;
+		padding: 24rpx 0 0 0;
+		overflow-y: auto;
+		background: #f6f7f9;
+
+		.cs-msg-item {
+			display: flex;
+			//   align-items: flex-end;
+			margin-bottom: 18rpx;
+			padding: 0 24rpx;
+
+			&.cs-msg-other {
+				flex-direction: row;
+
+				.cs-avatar {
+					margin-right: 12rpx;
+				}
+
+				.cs-msg-bubble {
+					background: #fff;
+					color: #1f1f1f;
+					border-top-left-radius: 0;
+					border-top-right-radius: 12rpx;
+					border-bottom-left-radius: 12rpx;
+					border-bottom-right-radius: 12rpx;
+				}
+			}
+
+			&.cs-msg-self {
+				flex-direction: row-reverse;
+
+				.cs-avatar {
+					margin-left: 12rpx;
+				}
+
+				.cs-msg-bubble {
+					background: #e6f6d9;
+					color: #1f1f1f;
+					border-top-right-radius: 0;
+					border-top-left-radius: 12rpx;
+					border-bottom-left-radius: 12rpx;
+					border-bottom-right-radius: 12rpx;
+				}
+			}
+
+			.cs-avatar {
+				width: 64rpx;
+				height: 64rpx;
+				border-radius: 50%;
+			}
+
+			.cs-msg-bubble {
+				max-width: 70vw;
+				min-height: 40rpx;
+				font-size: 28rpx;
+				padding: 18rpx 24rpx;
+				word-break: break-all;
+				box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+				margin-bottom: 2rpx;
+				display: flex;
+				align-items: center;
+			}
+		}
+
+		.cs-time-bar {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin: 18rpx 0 12rpx 0;
+
+			.cs-time-inner {
+				background: #fff;
+				color: #b2b2b2;
+				font-size: 24rpx;
+				border-radius: 16rpx;
+				padding: 8rpx 24rpx;
+				box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 2604);
+				display: inline-block;
+			}
+		}
+	}
+
+	.order-card {
+		background: #fff;
+		border-radius: 20rpx;
+		box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+		padding: 24rpx 24rpx 18rpx 24rpx;
+		margin: 24rpx;
+		position: absolute;
+		top: -26rpx;
+		transform: translateY(-100%);
+		font-size: 28rpx;
+		width: 670rpx;
+
+		.order-card-header {
+			display: flex;
+			align-items: flex-start;
+			position: relative;
+
+			.order-card-img {
+				width: 100rpx;
+				height: 100rpx;
+				border-radius: 12rpx;
+				margin-right: 18rpx;
+				flex-shrink: 0;
+			}
+
+			.order-card-info {
+				flex: 1;
+				display: flex;
+				flex-direction: column;
+				justify-content: flex-start;
+
+				.order-card-title {
+					font-size: 30rpx;
+					color: #1f1f1f;
+					font-weight: 500;
+					margin-bottom: 18rpx;
+					margin-top: 2rpx;
+					line-height: 1.3;
+					max-width: 450rpx;
+				}
+
+				.order-card-btn-box {
+					display: flex;
+					align-items: center;
+					justify-content: flex-end;
+
+					.order-card-btn {
+						font-family: "PingFang SC-Bold";
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #acf934;
+						background: #1f1f1f;
+						border-radius: 128rpx;
+						padding: 8rpx 14rpx;
+						line-height: 1.2;
+						margin: 0;
+					}
+				}
+			}
+
+			.order-card-close {
+				position: absolute;
+				right: -10rpx;
+				top: -10rpx;
+				font-size: 36rpx;
+				color: #1f1f1f;
+				background: #fff;
+				border-radius: 50%;
+				width: 34rpx;
+				height: 34rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				z-index: 2;
+			}
+		}
+
+		.order-card-row {
+			display: flex;
+			align-items: center;
+			margin-top: 12rpx;
+
+			.order-card-label {
+				color: #b2b2b2;
+				font-size: 26rpx;
+				width: 140rpx;
+				flex-shrink: 0;
+			}
+
+			.order-card-value {
+				color: #1f1f1f;
+				font-size: 26rpx;
+				margin-left: 12rpx;
+				word-break: break-all;
+			}
+		}
+	}
+
+	.cs-input-bar {
+		display: flex;
+		align-items: center;
+		background: #fff;
+		padding: 12rpx 16rpx;
+		border-top: 1rpx solid #ededed;
+		position: fixed;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		z-index: 10;
+		padding-bottom: calc(12rpx + var(--window-bottom));
+
+		.fake-input-bar {
+			display: flex;
+			align-items: center;
+			background: #f6f7f9;
+			border-radius: 24rpx;
+			padding: 12rpx 20rpx;
+			margin: 0 12rpx;
+			flex: 1;
+			min-height: 64rpx;
+			border: 1rpx solid #ededed;
+
+			.fake-input-placeholder {
+				color: #bbb;
+				font-size: 28rpx;
+				flex: 1;
+			}
+
+			.fake-input-icons {
+				display: flex;
+				align-items: center;
+
+			}
+		}
+
+		.fake-input-icon {
+			width: 40rpx;
+			height: 40rpx;
+			margin-left: 16rpx;
+		}
+
+		.cs-input-area {
+			display: flex;
+			align-items: flex-end;
+			flex-direction: column;
+			background: #fff;
+			border-radius: 32rpx;
+			padding: 8rpx 12rpx;
+			flex: 1;
+
+			.cs-textarea {
+				flex: 1;
+				min-height: 64rpx;
+				max-height: 120rpx;
+				overflow-y: auto;
+				border: none;
+				font-size: 28rpx;
+				background: #f6f7f9;
+				border-radius: 24rpx;
+				padding: 12rpx 20rpx;
+				resize: none;
+				width: 100%;
+			}
+
+			.bottom-bar {
+				width: 100%;
+				padding: 12rpx 0;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+			}
+
+			.send_btn {
+				background: #a6e22e;
+				color: #fff;
+				border-radius: 32rpx;
+				font-size: 28rpx;
+				padding: 26rpx 32rpx;
+				line-height: 0;
+				border: 1rpx solid transparent;
+
+				&.prohibit {
+					background: #fff;
+					border: 1rpx solid #999;
+					color: #999;
+				}
+			}
+		}
+	}
+
+	.emoji-panel {
+		position: fixed;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		z-index: 1000;
+		width: 100vw;
+		height: 100vh;
+
+		&.show {
+			transform: translateY(0);
+		}
+
+		.emoji-mask {
+			position: fixed;
+			left: 0;
+			right: 0;
+			top: 0;
+			bottom: 0;
+			background: rgba(0, 0, 0, 0.1);
+			z-index: 1001;
+		}
+
+		.emoji-grid {
+			position: relative;
+			z-index: 1002;
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: center;
+			padding-bottom: 24rpx;
+			max-height: 50vh;
+			width: 100vw;
+			border-top: 1rpx solid #ededed;
+
+			background: #fff;
+			padding: 12rpx 0 0 0;
+			box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.08);
+			overflow-y: auto;
+			transform: translateY(100%);
+			transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+			border-top: 20rpx solid #fff;
+
+			.emoji-item {
+				width: 60rpx;
+				height: 60rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				font-size: 36rpx;
+				color: #333;
+				margin: 8rpx;
+				border-radius: 8rpx;
+				padding: 8rpx;
+			}
+		}
+	}
+
+	.cs-msg-order-card-box {
+		display: flex;
+		flex-direction: row-reverse;
+
+		.order-card-avatar {
+			width: 64rpx;
+			height: 64rpx;
+			border-radius: 50%;
+			margin-left: 12rpx;
+			margin-right: 24rpx;
+		}
+
+		.cs-msg-order-card {
+			position: relative;
+			display: flex;
+			flex-direction: row;
+			align-items: flex-start;
+			background: #fff;
+			border-radius: 20rpx;
+			box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+			padding: 24rpx 24rpx 18rpx 24rpx;
+			margin: 24rpx 0 0 0;
+			width: 600rpx;
+			min-height: 160rpx;
+
+			.order-card-img {
+				width: 100rpx;
+				height: 100rpx;
+				border-radius: 12rpx;
+				margin-right: 18rpx;
+				flex-shrink: 0;
+			}
+
+			.order-card-info {
+				flex: 1;
+				display: flex;
+				flex-direction: column;
+				justify-content: flex-start;
+
+				.order-card-title {
+					font-size: 30rpx;
+					color: #1f1f1f;
+					font-weight: 500;
+					margin-bottom: 18rpx;
+					margin-top: 2rpx;
+					line-height: 1.3;
+					max-width: 350rpx;
+					word-break: break-all;
+				}
+
+				.order-card-btn-box {
+					display: flex;
+					align-items: center;
+					justify-content: flex-end;
+					margin-top: 12rpx;
+
+					.order-card-btn {
+						font-family: "PingFang SC-Bold";
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #1f1f1f;
+						background: #acf934;
+						border-radius: 128rpx;
+						padding: 8rpx 24rpx;
+						line-height: 1.2;
+						margin: 0;
+					}
+				}
+			}
+
+			.order-card-row {
+				display: flex;
+				align-items: center;
+				margin-top: 8rpx;
+
+				.order-card-label {
+					color: #b2b2b2;
+					font-size: 26rpx;
+					width: 140rpx;
+					flex-shrink: 0;
+				}
+
+				.order-card-value {
+					color: #1f1f1f;
+					font-size: 26rpx;
+					margin-left: 12rpx;
+					word-break: break-all;
+				}
+			}
+		}
+	}
+
+	.dropdown-menu {
+		position: absolute;
+		top: calc(100% + 10rpx);
+		right: 20rpx;
+		background-color: #ffffff;
+		border-radius: 20rpx;
+		padding: 0;
+		width: 200rpx;
+		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+		z-index: 100;
+		transform-origin: top right;
+		animation: dropdownAnimation 0.2s ease-out;
+		overflow: hidden;
+
+		.dropdown-item {
+			padding: 24rpx 0;
+			color: #333333;
+			font-size: 28rpx;
+			position: relative;
+			text-align: center;
+
+			&:not(:last-child)::after {
+				content: '';
+				position: absolute;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				height: 1rpx;
+				background-color: #EEEEEE;
+			}
+
+			&:active {
+				background-color: #f8f8f8;
+			}
+		}
+	}
+
+	@keyframes dropdownAnimation {
+		0% {
+			opacity: 0;
+			transform: scale(0.95) translateY(-5rpx);
+		}
+
+		100% {
+			opacity: 1;
+			transform: scale(1) translateY(0);
+		}
+	}
+
+}
+</style>

+ 112 - 46
pages/crowdFunding/customerService.vue

@@ -6,14 +6,14 @@
 			<view class="navbar-left">
 				<text class="fa fa-angle-left" @click="goBack"></text>
 				<view class="navbar-title one-omit">
-					时间是一种解药时间是一种解药时间是一种解药时间是一种解药时间是一种解药
+					{{ orderCardData.creator_nickname }}
 				</view>
 			</view>
 
 			<view class="navbar-right" @click="toggleDropdown">
 				<image src="@/static/icon/more2.png" style="width: 64rpx; height: 64rpx; margin-top: 15rpx"
 					mode="widthFix"></image>
-
+					
 				<view class="dropdown-menu" v-if="showDropdown">
 					<view class="dropdown-item" @tap="handleOption('report')">举报内容</view>
 				</view>
@@ -27,6 +27,9 @@
 				paddingBottom: (keyboardHeight ? keyboardHeight + 100 : 100) + 'rpx',
 			}">
 			<view v-for="(msg, idx) in chatList" :key="msg.id">
+				<template v-if="msg.message_type == 1 || msg.message_type == 2 || msg.message_type == 3 || msg.message_type == 4 || msg.message_type == 5 ">
+
+				
 				<view v-if="shouldShowTime(idx)" class="cs-time-bar">
 					<view class="cs-time-inner">{{ formatTime(msg.time) }}</view>
 				</view>
@@ -34,21 +37,22 @@
 					<view class="cs-msg-order-card-box">
 						<image class="order-card-avatar" :src="msg.avatar" />
 						<view class="cs-msg-order-card">
-							<image class="order-card-img" :src="msg.order.img" mode="aspectFill" />
+							<image class="order-card-img" v-if="msg.order.main_image" :src="msg.order.main_image"
+								mode="aspectFill" />
 							<view class="order-card-info">
 								<view class="order-card-title">{{ msg.order.title }}</view>
-								<view class="order-card-row">
+								<view class="order-card-row" v-if="msg.order.orderNo">
 									<text class="order-card-label">订单编号</text>
 									<text class="order-card-value">{{ msg.order.orderNo }}</text>
 								</view>
-								<view class="order-card-row">
+								<view class="order-card-row" v-if="msg.order.orderTime">
 									<text class="order-card-label">下单时间</text>
 									<text class="order-card-value">{{
 										msg.order.orderTime
 									}}</text>
 								</view>
 								<view class="order-card-btn-box">
-									<button class="order-card-btn">查看详情</button>
+									<button class="order-card-btn" @click="goDetails(msg.order)">查看详情</button>
 								</view>
 							</view>
 						</view>
@@ -68,8 +72,11 @@
 							<!-- 图片消息 -->
 							<template v-else-if="msg.message_type === 2">
 								<view style="position:relative;display:inline-block;">
-									<image :src="msg.media_url" mode="aspectFit" style="max-width: 180rpx; max-height: 180rpx; border-radius: 8rpx;" @tap="!msg.uploading && previewImage(msg.media_url)" />
-									<view v-if="msg.uploading" style="position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(255,255,255,0.7);display:flex;align-items:center;justify-content:center;">
+									<image :src="msg.media_url" mode="widthFix"
+										style="max-width: 180rpx;  border-radius: 8rpx;"
+										@tap="!msg.uploading && previewImage(msg.media_url)" />
+									<view v-if="msg.uploading"
+										style="position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(255,255,255,0.7);display:flex;align-items:center;justify-content:center;">
 										<text style="color:#a6e22e;font-size:24rpx;">{{ msg.progress || 0 }}%</text>
 									</view>
 								</view>
@@ -80,9 +87,10 @@
 							</template>
 							<!-- 视频消息 -->
 							<template v-else-if="msg.message_type === 4">
-								<video :src="msg.media_url" controls style="max-width: 220rpx; max-height: 180rpx; border-radius: 8rpx;" />
+								<video :src="msg.media_url" controls
+									style="max-width: 220rpx; max-height: 180rpx; border-radius: 8rpx;" />
 							</template>
-						 
+
 							<!-- 其它未知类型 -->
 							<template v-else>
 								<text style="color:#bbb">[未知消息类型]</text>
@@ -90,6 +98,7 @@
 						</view>
 					</view>
 				</template>
+			</template>
 			</view>
 			<view style="height: 200rpx; width: 100%"></view>
 			<view :id="'bottom-anchor'"></view>
@@ -99,27 +108,27 @@
 		<!-- 底部输入栏 -->
 		<view class="cs-input-bar" :style="{ bottom: keyboardHeight + 'rpx' }">
 			<!-- 广告条 -->
-			<view class="order-card" v-if="adShow">
+			<view class="order-card" v-if="adShow && zcId">
 				<view class="order-card-header">
-					<image class="order-card-img" src="/static/crowdFunding/top-img.png" mode="aspectFill" />
+					<image class="order-card-img" :src="orderCardData.main_image" mode="aspectFill" />
 					<view class="order-card-info">
-						<view class="order-card-title one-omit">【Woh】灯塔 塔罗牌 治愈风泛伟特系</view>
+						<view class="order-card-title one-omit">{{ orderCardData.title }}</view>
 						<view class="order-card-btn-box">
 							<button class="order-card-btn" @click="sendOrderCardMsg()">
 								发给客服
 							</button>
-						</view>
+						</view> 
 					</view>
 					<image class="order-card-close" @click="closeOrderCard" src="@/static/icon/wd_icon_guanbi.png"
 						mode="widthFix"></image>
 				</view>
-				<view class="order-card-row">
+				<view class="order-card-row" v-if="orderCardData.orderNo">
 					<text class="order-card-label">订单编号</text>
-					<text class="order-card-value">12201544521215415415415</text>
+					<text class="order-card-value">{{ orderCardData.orderNo }}</text>
 				</view>
-				<view class="order-card-row">
+				<view class="order-card-row" v-if="orderCardData.orderTime">
 					<text class="order-card-label">下单时间</text>
-					<text class="order-card-value">2025-05-27 09:35:30</text>
+					<text class="order-card-value">{{ orderCardData.orderTime }}</text>
 				</view>
 			</view>
 
@@ -143,7 +152,7 @@
 						<image @tap="upload" src="/static/icon/icon-picture.png" class="fake-input-icon" />
 						<image @tap="toggleEmojiPanel" src="/static/icon/icon-expression.png" class="fake-input-icon" />
 					</view>
-					<view :class="['send_btn', inputValue.trim() ? '' : 'prohibit']" @tap="sendMsg">发送</view>
+					<view :class="['send_btn', inputValue.trim() ? '' : 'prohibit']" @tap="sendMsg(1)">发送</view>
 				</view>
 			</view>
 		</view>
@@ -178,16 +187,20 @@ export default {
 			emojiList: ["😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", "😙", "😚", "🙂", "🤗", "🤩", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯", "😪", "😫", "🥱", "😴", "😌", "😛", "😜", "😝", "🤤", "😒", "😓", "😔", "😕", "🙃", "🤑", "😲", "☹️", "🙁", "😖", "😞", "😟", "😤", "😢", "😭", "😦", "😧", "😨", "😩", "🤯", "😬", "😰", "😱", "🥵", "🥶", "😳", "🤪", "😵", "😡", "😠", "🤬", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😇", "🥳", "🥺", "🤠", "😈", "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "💩", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾", "🙈", "🙉", "🙊", "💋", "💌", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️", "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍", "💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👋", "🤚", "🖐️", "✋", "🖖", "👌", "🤏", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍", "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦶", "👂", "👃", "🧠", "🦷", "🦴", "��", "👁️", "👅", "👄"],
 			conversationId: 0,
 			creatorId: 0,
+			zcId: 0,
 			lastMsgId: 0,
 			pageSize: 20,
 			userInfo: {},
 			showRealInput: false, // 控制显示真输入框还是假输入框
+			orderCardData: {},
 		};
 	},
 	onLoad(options) {
 		this.creatorId = options.id || 0;
+		this.zcId = options.zc_id || 0;
 		this.fetchMessages();
 		this.startPolling();
+		this.getOrderCardData()
 	},
 	onHide() {
 		this.clearPolling();
@@ -223,7 +236,8 @@ export default {
 					conversation_id: this.conversationId,
 					last_id: isAppend ? this.lastMsgId : 0,
 					page_size: this.pageSize,
-					zc_id: this.creatorId
+					// page_size: 40,
+					zc_id: this.zcId
 				},
 				success: (res) => {
 					if (res.data && res.data.success === 'yes' && res.data.data) {
@@ -231,24 +245,31 @@ export default {
 						this.userInfo = user_info || {};
 						this.conversationId = conversation?.id || 0;
 						// 格式化消息,保留 message_type、media_url 等字段
-						const msgList = (messages || []).map(msg => ({
-							id: msg.id,
-							content: msg.content,
-							type: msg.from_type === 1 ? 'user' : 'customerService',
-							avatar: msg.from_type === 1 ? (user_info.avatar || '/static/makedetail/characterProfilePicture.png') : '/static/home/avator.png',
-							time: msg.create_time,
-							message_type: msg.message_type, // 消息类型
-							media_url: msg.media_url, // 媒体文件URL
-							progress: msg.progress,
-							uploading: msg.uploading
-						}));
+						const msgList = (messages || []).map(msg => {
+							let returnValue = {
+								id: msg.id,
+								content: msg.content,
+								type: msg.from_type === 1 ? 'user' : 'customerService',
+								avatar: msg.from_type === 1 ? (user_info.avatar || '/static/makedetail/characterProfilePicture.png') : '/static/home/avator.png',
+								time: msg.create_time,
+								message_type: msg.message_type, // 消息类型
+								media_url: msg.media_url, // 媒体文件URL
+								progress: msg.progress,
+								uploading: msg.uploading
+							}
+							if (msg.message_type == 5) {
+								returnValue.order = JSON.parse(msg.content);
+							}
+							return returnValue;
+						});
+						console.log(msgList, "消息列表");
 						// 合并未上传完成的临时消息
 						const tempMsgs = this.chatList.filter(m => m.uploading);
 						let newList;
 						if (isAppend) {
-							newList = [...msgList.reverse(), ...this.chatList.filter(m => !m.uploading), ...tempMsgs];
+							newList = [...msgList, ...this.chatList.filter(m => !m.uploading), ...tempMsgs];
 						} else {
-							newList = [...msgList.reverse(), ...tempMsgs];
+							newList = [...msgList, ...tempMsgs];
 						}
 						this.chatList = newList;
 						// 记录最后一条消息ID
@@ -270,10 +291,13 @@ export default {
 			});
 		},
 		// 发送消息
-		sendMsg() {
-			if (!this.inputValue.trim()) return;
+		sendMsg(message_type) {
+
+			if (!this.inputValue.trim() && message_type == 1) return;
 			const content = this.inputValue;
 			this.inputValue = "";
+			console.log(content, "发送消息", message_type);
+
 			uni.request({
 				url: this.$apiHost + '/App/kefuSendMessage',
 				method: 'POST',
@@ -287,9 +311,9 @@ export default {
 					skey: getApp().globalData.skey,
 					creator_id: this.creatorId,
 					conversation_id: this.conversationId,
-					message_type: 1, // 文本
+					message_type: message_type, // 文本
 					content: content,
-					zc_id: this.creatorId
+					zc_id: this.zcId
 				},
 				success: (res) => {
 					if (res.data && res.data.success === 'yes') {
@@ -306,7 +330,7 @@ export default {
 		},
 		closeOrderCard() {
 			this.adShow = false;
-		},
+		}, 
 		shouldShowTime(idx) {
 			if (idx === 0) return true;
 			// 找到上一个显示时间条的消息
@@ -370,8 +394,8 @@ export default {
 		sendOrderCardMsg() {
 			this.chatList.push({
 				id: Date.now(),
-				type: "orderCard",
-				avatar: "/static/makedetail/characterProfilePicture.png", // 用户头像
+				message_type: 5,
+				avatar: this.avatar, // 用户头像
 				order: {
 					img: "/static/crowdFunding/top-img.png",
 					title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系",
@@ -380,6 +404,9 @@ export default {
 				},
 				time: this.getNowTime(),
 			});
+			this.sendMsg(5);
+
+
 			this.$nextTick(() => {
 				this.closeOrderCard();
 				setTimeout(() => {
@@ -408,7 +435,7 @@ export default {
 					});
 					break;
 			}
-		}, 
+		},
 		showInputAndFocus() {
 			this.showRealInput = true;
 			this.$nextTick(() => {
@@ -532,7 +559,7 @@ export default {
 					message_type: 2, // 2为图片
 					content: '', // 图片消息content可为空
 					media_url: imgUrl, // 图片地址
-					zc_id: this.creatorId
+					zc_id: this.zcId
 				},
 				success: (res) => {
 					if (res.data && res.data.success === 'yes') {
@@ -546,11 +573,49 @@ export default {
 				}
 			});
 		},
+		goDetails(item) {
+			console.log(item, 'item');
+			let url = '';
+			if (item.orderNo) {
+				url = '/pages/crowdFunding/orderDetails?id=' + item.orderNo;
+			} else {
+				url = '/pages/crowdFunding/crowdfundingDetails?id=' + item.id;
+			}
+			uni.navigateTo({
+				url: url
+			});
+		},
+		getOrderCardData() {
+			if (this.zcId) {
+				uni.request({
+					url: this.$apiHost + '/crowdfund/detail',
+					method: 'GET',
+					data: {
+						id: this.zcId,
+						uuid: getApp().globalData.uuid,
+						skey: getApp().globalData.skey
+
+					},
+					success: (res) => {
+						if (res.data && res.data.success === 'yes' && res.data.data) {
+							this.orderCardData = res.data.data;
+							console.log(this.orderCardData, 'this.orderCardData');
+							// 可根据接口返回字段设置isFavorite等
+						}
+					}
+				});
+			}
+		},
 		// 图片预览
 		previewImage(url) {
+			// 收集当前消息列表中的所有图片URL
+			const imageUrls = this.chatList
+				.filter(msg => msg.message_type === 2 && msg.media_url)
+				.map(msg => msg.media_url);
+			const currentIndex = imageUrls.indexOf(url);
 			uni.previewImage({
-				current: url,
-				urls: [url]
+				current: currentIndex >= 0 ? currentIndex : 0,
+				urls: imageUrls
 			});
 		},
 	},
@@ -704,7 +769,8 @@ export default {
 		padding: 24rpx 24rpx 18rpx 24rpx;
 		margin: 24rpx;
 		position: absolute;
-		top: -280rpx;
+		top: -26rpx;
+		transform: translateY(-100%);
 		font-size: 28rpx;
 		width: 670rpx;
 
@@ -946,7 +1012,7 @@ export default {
 	.cs-msg-order-card-box {
 		display: flex;
 		flex-direction: row-reverse;
-
+		margin-bottom: 20rpx;
 		.order-card-avatar {
 			width: 64rpx;
 			height: 64rpx;

+ 133 - 57
pages/crowdFunding/orderConfirm.vue

@@ -1,40 +1,39 @@
 <template>
   <view class="order-confirm-page">
-    <view class="address-card scale-tap" @click="goPage('/pages/crowdFunding/receivingAddress')">
-      <view class="address-content">
+    <view class="address-card scale-tap" @click="selectAddress()">
+
+      <view class="address-content" v-if="address.id != 0">
         <view class="row">
-          <text class="name">{{ address.name }}</text>
+          <text class="name">{{ address.realname }}</text>
           <text class="mobile">{{ address.mobile }}</text>
-          <text class="default" v-if="address.isDefault">默认</text>
+          <text class="default" v-if="address.is_default == 'yse'">默认</text>
+        </view>
+        <view class="address">收获地址:{{ address.area + address.address }}</view>
+      </view>
+      <view class="address-content" v-else>
+        <view class="row">
+          <text class="name" style="color: red;">请选择地址</text>
         </view>
-        <view class="address">收获地址:{{ address.fullAddress }}</view>
       </view>
       <image class="arrow" src="@/static/crowdFunding/right.png" />
     </view>
     <view class="order-section">
       <view class="order-row">
         <text>回报内容</text>
-        <text class="right">({{ reward }}) ¥{{ price }}</text>
+        <text class="right">({{ selectedSpec && selectedSpec.selectedReward && selectedSpec.selectedReward.title }}) ¥{{
+          price }}</text>
       </view>
       <view class="order-row">
         <text>众筹数量</text>
         <view class="right">
-          <image
-            src="@/static/icon/stepping_minus.png"
-            @click="minus"
-            class="minus"
-          />
+          <image src="@/static/icon/stepping_minus.png" @click="minus" class="minus" />
           <text class="num">{{ count }}</text>
-          <image
-            src="@/static/icon/stepping_add.png"
-            @click="plus"
-            class="plus"
-          />
+          <image src="@/static/icon/stepping_add.png" @click="plus" class="plus" />
         </view>
       </view>
       <view class="order-row">
         <text>运费</text>
-        <text class="right">包邮</text>
+        <text class="right">{{ !shippingFee ? '包邮' : shippingFee }}</text>
       </view>
     </view>
     <view class="remark-section">
@@ -42,37 +41,21 @@
       <input class="remark-input" placeholder="选填" v-model="remark" />
     </view>
     <view class="pay-section">
-      <view
-        class="pay-item"
-        :class="{ checked: payType === 'wx' }"
-        @click="payType = 'wx'"
-      >
+      <view class="pay-item" :class="{ checked: payType === 'wx' }" @click="payType = 'wx'">
         <image src="@/static/icon/weixin_logo.png" class="pay-icon" />
         <text>微信支付</text>
-        <image
-          :src="
-            payType === 'wx'
-              ? '/static/icon/wd_icon_gouxuan05.png'
-              : '/static/icon/wd_icon_gouxuan04.png'
-          "
-          class="check"
-        />
+        <image :src="payType === 'wx'
+          ? '/static/icon/wd_icon_gouxuan05.png'
+          : '/static/icon/wd_icon_gouxuan04.png'
+          " class="check" />
       </view>
-      <view
-        class="pay-item"
-        :class="{ checked: payType === 'alipay' }"
-        @click="payType = 'alipay'"
-      >
+      <view class="pay-item" :class="{ checked: payType === 'alipay' }" @click="payType = 'alipay'">
         <image src="@/static/icon/zhifubao_logon.png" class="pay-icon" />
         <text>支付宝</text>
-        <image
-          :src="
-            payType === 'alipay'
-              ? '/static/icon/wd_icon_gouxuan05.png'
-              : '/static/icon/wd_icon_gouxuan04.png'
-          "
-          class="check"
-        />
+        <image :src="payType === 'alipay'
+          ? '/static/icon/wd_icon_gouxuan05.png'
+          : '/static/icon/wd_icon_gouxuan04.png'
+          " class="check" />
       </view>
     </view>
     <view class="protocol-section">
@@ -102,20 +85,45 @@ export default {
   data() {
     return {
       address: {
-        name: "戴驿宸",
-        mobile: "17788196551",
-        isDefault: true,
-        fullAddress: "浙江省杭州市滨江区西兴街道启悦府",
+        id: 0
       },
-      reward: "灯塔MINI版",
-      price: 29.9,
+      price: 0,
       count: 1,
       remark: "",
       payType: "wx",
       isSubmitting: false,
       lastClickTime: 0,
       linkid: '',
+      selectedSpec: null,
+      detail: null,
+      shippingFee: 0,
     };
+  },
+  onLoad(options) {
+    console.log('options', options);
+    if (options.orderId) { 
+    } else {
+      const eventChannel = this.getOpenerEventChannel();
+      eventChannel.on('acceptDataFromOpener', (data) => {
+        this.selectedSpec = data.selectedSpec;
+        this.detail = data.detail;
+        this.price = this.selectedSpec && this.selectedSpec.selectedReward && this.selectedSpec.selectedReward.price || 0
+        console.log('接收到的数据:', this.selectedSpec, this.detail);
+      });
+
+      eventChannel.on('acceptAddress', (address) => {
+        this.address = address;
+        console.log('接收到的地址:', this.address);
+      });
+      if (this.address.id == 0) {
+        this.getAddress();
+      }
+      this.getPostage();
+    }
+  },
+  onShow() {
+
+
   },
   methods: {
     goBack() {
@@ -126,11 +134,69 @@ export default {
     },
     minus() {
       if (this.count > 1) this.count--;
+      this.getPostage()
     },
     plus() {
       this.count++;
+      this.getPostage()
+    },
+   
+    getAddress() {
+      // 获取默认地址
+      uni.request({
+        url: this.$apiHost + '/Address/getdefault',
+        method: 'GET',
+        data: {
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey
+
+        },
+        success: (res) => {
+          if (res.data && res.data.info) {
+            this.address = res.data.info;
+            console.log(res.data.info, '获取到的默认地址');
+          }
+
+
+        }
+      });
+
     },
+    getPostage() {
+      // 获取默认地址
+      uni.request({
+        url: this.$apiHost + '/crowdfund/calculate-shipping',
+        method: 'GET',
+        data: {
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey,
+          num: this.count,
+          area: this.address.area,
+          reward_id: this.selectedSpec && this.selectedSpec.selectedReward && this.selectedSpec.selectedReward.id
+        },
+        success: (res) => {
+          if (res.data && res.data.success == 'yes') {
+            console.log(res.data.data, '获取到邮费');
+            this.shippingFee = res.data.data.shipping_fee
+          }
+
+
+        }
+      });
+    },
+    selectAddress() {
+      uni.navigateTo({
+        url: '/pages/crowdFunding/receivingAddress?isSelectAddress=true',
+        success: function (res) {
+          // 通过 eventChannel 向被打开页面传送数据
+          res.eventChannel.emit('acceptDataFromOpener', { selectedSpec: this.selectedSpec, detail: this.detail });
+        }.bind(this)
+      });
+    },
+
+
     async submit() {
+
       const now = Date.now();
       if (now - this.lastClickTime < 3000) {
         uni.showToast({ title: "请勿频繁点击", icon: "none" });
@@ -144,15 +210,16 @@ export default {
       // 创建订单
       uni.request({
         url: this.$apiHost + '/Order/submit',
-        method: 'POST',
+        method: 'GET',
         data: {
           uuid: getApp().globalData.uuid,
           // 这里根据你的业务传递商品、数量、备注、支付方式等
-          product_id: this.productId, // 你需要在data或props中补充
-          count: this.count,
-          remark: this.remark,
+          type: 'buyCrowdfund',
+          reward_id: this.selectedSpec.selectedReward.id,
+          num: this.count,
+          beizu: this.remark,
           payType: this.payType,
-          type: 'crowdFunding'
+          address_id: this.address.id
         },
         header: {
           'content-type': 'application/json',
@@ -248,6 +315,7 @@ export default {
 page {
   background: #f6faf6;
 }
+
 .order-confirm-page {
   min-height: 100vh;
   background: #f6faf6;
@@ -280,11 +348,12 @@ page {
     display: flex;
     align-items: center;
     justify-content: space-between;
-    box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
+    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
 
     .address-content {
       flex: 1;
       min-width: 0;
+
       .row {
         display: flex;
         align-items: center;
@@ -296,11 +365,13 @@ page {
           margin-right: 18rpx;
           color: #222;
         }
+
         .mobile {
           font-size: 32rpx;
           margin-right: 18rpx;
           color: #222;
         }
+
         .default {
           font-size: 22rpx;
           color: #fff;
@@ -315,6 +386,7 @@ page {
           color: #acf934;
         }
       }
+
       .address {
         font-size: 26rpx;
         color: #666;
@@ -325,9 +397,10 @@ page {
         max-width: 600rpx;
       }
     }
+
     .arrow {
       width: 32rpx;
-      height: 32rpx; 
+      height: 32rpx;
       flex-shrink: 0;
     }
   }
@@ -467,11 +540,13 @@ page {
       display: flex;
       align-items: baseline;
       margin-right: 32rpx;
+
       .label {
         color: #b2b2b2;
         font-size: 28rpx;
         margin-right: 8rpx;
       }
+
       .price {
         color: #222;
         font-size: 32rpx;
@@ -497,7 +572,8 @@ page {
     }
   }
 }
-.bom-reserveASeat{
+
+.bom-reserveASeat {
   width: 100%;
   height: calc(var(--window-bottom) + 100rpx);
 }

+ 341 - 82
pages/crowdFunding/orderDetail.vue

@@ -6,15 +6,9 @@
         <text class="fa fa-angle-left" @click="goBack"></text>
       </view>
 
-      <view
-        class="navbar-right scale-tap"
-        @click="goPages('/pages/crowdFunding/customerService')"
-      >
-        <image
-          src="@/static/crowdFunding/customer-service-btn.png"
-          style="width: 60rpx; height: 60rpx"
-          mode="widthFix"
-        ></image>
+      <view class="navbar-right scale-tap" @click="goPages('/pages/crowdFunding/customerService')">
+        <image src="@/static/crowdFunding/customer-service-btn.png" style="width: 60rpx; height: 60rpx" mode="widthFix">
+        </image>
       </view>
     </view>
 
@@ -26,69 +20,62 @@
     </view>
 
     <!-- 收货信息 -->
-    <view
-      class="address-card scale-tap"
-      @click="goPages('/pages/crowdFunding/receivingAddress')"
-    >
+    <view class="address-card scale-tap" @click="goPages('/pages/crowdFunding/receivingAddress')">
       <view class="row">
-        <text class="name">{{ address.name }}</text>
+        <text class="name">{{ address.realname }}</text>
         <text class="mobile">{{ address.mobile }}</text>
-        <text class="default" v-if="address.isDefault">默认</text>
+        <text class="default" v-if="address.is_default == 'yse'">默认</text>
       </view>
-      <view class="address">{{ address.fullAddress }}</view>
+      <view class="address">收获地址:{{ address.area + address.address }}</view>
     </view>
 
     <!-- 商品卡片 -->
     <view class="product-card">
-      <view class="product-top">
+      <view class="product-top" @click="goPages('/pages/crowdFunding/crowdfundingDetails?id=' + product.id)">
         <image class="product-img" :src="product.img" />
         <view class="product-info">
-          <view class="product-title"
-            ><text>{{ product.title }} </text>
-            <image
-              class="arrow"
-              mode="widthFix"
-              src="@/static/crowdFunding/right.png"
-          /></view>
+          <view class="product-title"><text class="two-omit">{{ product.title }} </text>
+            <image class="arrow" mode="widthFix" src="@/static/crowdFunding/right.png" />
+          </view>
           <view class="product-desc">
             {{ product.desc }}
           </view>
-        </view></view
-      >
+        </view>
+      </view>
       <view class="product-bom">
-        <view class="product-spec"
-          >回报档:¥{{ product.price }}{{ product.spec }}
-          <text class="count">x{{ product.count }}</text></view
-        >
+        <view class="product-spec">回报档:¥{{ product.price }} {{ product.spec }}
+          <text class="count">x{{ product.count }}</text>
+        </view>
         <view class="product-time">
           预计发货时间:{{ product.deliveryTime }}
         </view>
-        <view class="product-tip">{{ product.tip }}</view>
+        <!-- <view class="product-tip">{{ product.tip }}</view> -->
       </view>
 
       <!-- 费用明细 -->
-      <view class="fee-row">
+      <!-- <view class="fee-row">
         <text>运费</text>
         <text>包邮</text>
-      </view>
+      </view> -->
       <view class="fee-row total">
-        <text>实付金额</text>
+        <text>金额</text>
         <text class="total-price">¥{{ product.total }}</text>
       </view>
     </view>
 
     <!-- 订单信息 -->
     <view class="order-info-card">
-      <view class="info-row">
+      <view class="info-row" v-if="order.orderNo">
         <text>订单编号</text>
         <view><text>{{ order.orderNo }}</text>
-          <text class="copy-btn" @click="copy(order.orderNo)">复制</text></view>
+          <text class="copy-btn" @click="copy(order.orderNo)">复制</text>
+        </view>
       </view>
-      <view class="info-row">
+      <view class="info-row" v-if="order.createTime">
         <text>下单时间</text>
         <text>{{ order.createTime }}</text>
       </view>
-      <view class="info-row">
+      <view class="info-row" v-if="order.payTime">
         <text>付款时间</text>
         <text>{{ order.payTime }}</text>
       </view>
@@ -96,26 +83,62 @@
 
     <!-- 底部操作栏 -->
     <view class="order-bottom">
-      <template v-if="statusType === 'waitPay'">
+      <template v-if="status == 0">
         <view class="btn scale-tap btn-cancel" @click="cancelOrder">取消订单</view>
         <view class="btn scale-tap btn-pay" @click="payOrder">立即支付</view>
       </template>
-      <template v-else-if="statusType === 'waitSend'">
+      <template v-else-if="status == 1">
         <view class="btn scale-tap btn-refund" @click="refundOrder">申请退款</view>
       </template>
-      <template v-else-if="statusType === 'finish'">
-        <view class="btn scale-tap btn-delete" @click="deleteOrder">删除订单</view>
-        <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view>
+      <template v-else-if="status == 2">
+        <view class="btn scale-tap btn-pay" @click="confirmOrder">确认收货</view>
+        <!-- <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view> -->
       </template>
-      <template v-else-if="statusType === 'waitComment'">
+      <template v-else-if="status == 3 || status == 5 || status == 9">
         <view class="btn scale-tap btn-delete" @click="deleteOrder">删除订单</view>
-        <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view>
+        <!-- <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view> -->
+      </template>
+      <template v-else-if="status == 6">
+        <view class="btn   btn-delete " style="background: #eee;">退款中</view>
+        <!-- <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view> -->
+      </template>
+      <template v-else-if="status == 8">
+        <view class="btn   btn-delete" style="background: #eee;">已关闭</view>
+        <!-- <view class="btn scale-tap btn-comment" @click="commentOrder">去评价</view> -->
       </template>
       <template v-else>
-        <view class="btn scale-tap btn-delete" @click="deleteOrder">删除订单</view>
+        <!-- <view class="btn scale-tap btn-delete" @click="deleteOrder">删除订单</view> -->
       </template>
     </view>
-  </view> 
+
+    <!-- 支付方式选择弹窗 -->
+    <uni-popup ref="paymentPopup" type="bottom">
+      <view class="payment-popup">
+        <view class="popup-header">
+          <view class="popup-title">选择支付方式</view>
+        </view>
+        <view class="payment-options">
+          <view class="payment-option" @tap="selectPayment('alipay')">
+            <image class="payment-icon" src="../../static/icon/pay_ali.png" mode="aspectFit"></image>
+            <view class="payment-name">支付宝支付</view>
+            <image class="payment-select"
+              :src="paymentMethod === 'alipay' ? '../../static/icon/wd_icon_gouxuan05.png' : '../../static/icon/wd_icon_gouxuan04.png'"
+              mode="aspectFit"></image>
+          </view>
+          <view v-if="isWeChatPay" class="payment-option" @tap="selectPayment('wechat')">
+            <image class="payment-icon" src="../../static/icon/pay_wx.png" mode="aspectFit"></image>
+            <view class="payment-name">微信支付</view>
+            <image class="payment-select"
+              :src="paymentMethod === 'wechat' ? '../../static/icon/wd_icon_gouxuan05.png' : '../../static/icon/wd_icon_gouxuan04.png'"
+              mode="aspectFit"></image>
+          </view>
+        </view>
+        <view class="confirm-payment" @tap="confirmPayment">立即支付</view>
+      </view>
+    </uni-popup>
+    <!-- 提示框 -->
+    <DialogBox ref="DialogBox"></DialogBox>
+  </view>
 </template>
 
 <script>
@@ -123,32 +146,22 @@ export default {
   data() {
     return {
       statusType: "waitPay", // waitPay, waitSend, finish, waitComment, fail
-      statusTitle: "支付失败", // 根据statusType动态切换
+      status: "",
+      statusTitle: "", // 根据statusType动态切换
       statusIcon: "loading", // 可根据状态切换icon   loading  fail  success
-      address: {
-        name: "戴驿宸",
-        mobile: "17788196551",
-        isDefault: true,
-        fullAddress: "浙江省杭州市滨江区西兴街道启悦府1202212121212211212",
-      },
-      product: {
-        img: "/static/crowdFunding/top-img.png",
-        title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-        desc: "",
-        spec: "灯塔MINI版",
-        price: 398,
-        count: 1,
-        deliveryTime: "2025年8月份",
-        tip: "温馨提示:该链接仅购买线下实物卡片!不含线上卡牌壁纸",
-        total: 398,
-      },
-      order: {
-        orderNo: "12201544521215415415",
-        createTime: "2025-05-27 09:35:30",
-        payTime: "2025-05-27 09:35:30",
-      },
+      address: {},
+      product: {},
+      order: {},
+      paymentMethod: 'alipay', // 默认支付宝支付
+      isWeChatPay: true, // 是否显示微信支付选项
+      orderId: "",
     };
   },
+  onLoad(options) {
+    this.getOrderDetail(options.orderId);
+    this.orderId = options.orderId;
+
+  },
   methods: {
     goBack() {
       uni.navigateBack();
@@ -156,14 +169,148 @@ export default {
     goPages(url) {
       uni.navigateTo({ url });
     },
+
     copy(val) {
       uni.setClipboardData({ data: val });
     },
-    cancelOrder() {},
-    payOrder() {},
-    refundOrder() {},
-    deleteOrder() {},
-    commentOrder() {},
+    cancelOrder() {
+      this.$refs["DialogBox"].confirm({
+        title: "提示",
+        content: "确定要取消订单吗?",
+        DialogType: "inquiry",
+        btn1: "否",
+        btn2: "是",
+        animation: 0,
+      }).then((res) => {
+        if (res) {
+          this.orderAction('cancel');
+        }
+      });
+    },
+    payOrder() {
+      this.$refs.paymentPopup.open();
+    },
+    selectPayment(method) {
+      this.paymentMethod = method;
+    },
+    confirmPayment() {
+      this.orderAction('pay', this.paymentMethod);
+      this.$refs.paymentPopup.close();
+    },
+    refundOrder() {
+      this.$refs.DialogBox.confirm({
+        title: "提示",
+        content: "确定要申请退款吗?",
+        DialogType: "inquiry",
+        btn1: "否",
+        btn2: "是",
+        animation: 0,
+      }).then((res) => {
+        if (res) {
+          this.orderAction('refund');
+        }
+      });
+    },
+    deleteOrder() {
+      this.$refs.DialogBox.confirm({
+        title: "提示",
+        content: "确定要删除订单吗?",
+        DialogType: "inquiry",
+        btn1: "否",
+        btn2: "是",
+        animation: 0,
+      }).then((res) => {
+        if (res) {
+          this.orderAction('del');
+        }
+      });
+    },
+    confirmOrder() {
+      this.$refs.DialogBox.confirm({
+        title: "提示",
+        content: "是否要确认收货吗?",
+        DialogType: "inquiry",
+        btn1: "否",
+        btn2: "是",
+        animation: 0,
+      }).then((res) => {
+        if (res) {
+          this.orderAction('finish');
+        }
+      });
+    },
+    commentOrder() { },
+    orderAction(act, payType = '') {
+      uni.request({
+        url: this.$apiHost + '/Order/action',
+        method: 'GET',
+        data: {
+          order_id: this.orderId,
+          act: act,
+          payType: payType,
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey
+        },
+        success: (res) => {
+          console.log(res.data, "订单操作结果");
+          if (res.data && res.data.success == 'yes') {
+            uni.showToast({ title: res.data.str, icon: 'success' });
+            this.getOrderDetail(this.order.orderNo);
+          } else {
+            uni.showToast({ title: res.data.message || '操作失败', icon: 'none' });
+          }
+        },
+        fail: () => {
+          uni.showToast({ title: '操作失败', icon: 'none' });
+        }
+      });
+    },
+    getOrderDetail(orderId) {
+      uni.request({
+        url: this.$apiHost + '/Order/detail?order_id=' + orderId,
+        method: 'GET',
+        data: {
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey
+        },
+        success: (res) => {
+          console.log(res.data.data, "获取订单详情");
+          if (res.data && res.data.success == 'yes') {
+            let data = res.data.data;
+            if (data.address) {
+              this.address = JSON.parse(data.address);
+            }
+            this.order = {
+              orderNo: data.linkid,
+              createTime: data.create_time,
+              payTime: data.order_time,
+            }
+            if (data.crowdfund) {
+              this.product = {
+                price: data.crowdfund.price,
+                img: data.crowdfund.image,
+                title: data.crowdfund.title,
+                desc: "",
+                spec: data.crowdfund.title2,
+                count: 1,
+                total: data.money,
+                deliveryTime: data.crowdfund.delivery,
+                id: data.crowdfund.id,
+                // tip: "温馨提示:该链接仅购买线下实物卡片!不含线上卡牌壁纸",
+              }
+            }
+            this.status = data.status;
+            this.statusTitle = data.status_name;
+          }
+        },
+        fail: () => {
+          uni.showToast({ title: '获取订单详情失败', icon: 'none' });
+        },
+        complete: () => {
+          uni.hideLoading();
+        }
+      });
+    },
   },
   mounted() {
     // 可根据实际订单状态设置statusType/statusTitle/statusIcon
@@ -176,6 +323,7 @@ export default {
 .order-detail-page {
   min-height: 100vh;
   background: #f2f6f2;
+
   .custom-navbar {
     display: flex;
     flex-direction: row;
@@ -211,42 +359,49 @@ export default {
       align-items: center;
     }
   }
+
   .status-bar {
     display: flex;
     align-items: center;
     padding: 32rpx 32rpx 0 32rpx;
+
     .status-icon {
       width: 40rpx;
       height: 40rpx;
       margin-right: 12rpx;
     }
+
     .status-title {
       font-size: 36rpx;
       font-weight: bold;
       color: #1F1F1F;
     }
   }
+
   .address-card {
     background: #fff;
     border-radius: 16rpx;
     margin: 24rpx 16rpx 0 16rpx;
     padding: 24rpx;
-    background: url("../../static/crowdFunding/order-detail-card-bg.png")
-        no-repeat top right / auto 100%,
+    background: url("../../static/crowdFunding/order-detail-card-bg.png") no-repeat top right / auto 100%,
       #fff;
+
     .row {
       display: flex;
       align-items: center;
       margin-bottom: 8rpx;
+
       .name {
         font-size: 30rpx;
         font-weight: bold;
         margin-right: 18rpx;
       }
+
       .mobile {
         font-size: 30rpx;
         margin-right: 18rpx;
       }
+
       .default {
         font-size: 22rpx;
         color: #acf934;
@@ -256,19 +411,23 @@ export default {
         margin-right: 12rpx;
       }
     }
+
     .address {
       font-size: 26rpx;
       color: #666;
     }
   }
+
   .product-card {
     background: #fff;
     border-radius: 16rpx;
     margin: 24rpx 16rpx 0 16rpx;
     padding: 24rpx;
+
     .product-top {
       display: flex;
       align-items: center;
+      justify-content: space-between;
 
       .product-img {
         width: 120rpx;
@@ -276,20 +435,35 @@ export default {
         border-radius: 12rpx;
         margin-right: 18rpx;
       }
+
       .product-info {
         flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
         .product-title {
+          width: 100%;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
           font-size: 28rpx;
           font-weight: bold;
           color: #1f1f1f;
           display: flex;
           align-items: center;
+
+          .two-omit {
+            width: 400rpx;
+          }
+
           .arrow {
             width: 60rpx;
             height: 60rpx;
-            margin-left: 140rpx;
+            // margin-left: 140rpx;
           }
         }
+
         .product-desc {
           font-size: 24rpx;
           color: #1F1F1F;
@@ -297,8 +471,10 @@ export default {
         }
       }
     }
+
     .product-bom {
       padding-top: 15rpx;
+
       .product-spec {
         font-size: 26rpx;
         color: #1F1F1F;
@@ -306,6 +482,7 @@ export default {
         display: flex;
         align-items: center;
         justify-content: space-between;
+
         .count {
           color: #888;
           font-size: 22rpx;
@@ -313,11 +490,13 @@ export default {
           margin-top: 8rpx;
         }
       }
+
       .product-time {
         font-size: 24rpx;
         color: #b2b2b2;
         margin-bottom: 8rpx;
       }
+
       .product-tip {
         font-size: 26rpx;
         color: #b2b2b2;
@@ -326,12 +505,14 @@ export default {
         padding: 8rpx 12rpx;
       }
     }
+
     .arrow {
       width: 32rpx;
       height: 32rpx;
       margin-left: 8rpx;
     }
   }
+
   .fee-row {
     display: flex;
     justify-content: space-between;
@@ -340,36 +521,44 @@ export default {
     height: 64rpx;
     font-size: 28rpx;
     color: #1F1F1F;
+
     text:first-child {
       color: #999;
     }
+
     &.total {
       font-weight: bold;
       color: #1f1f1f;
       justify-content: flex-end;
+
       text:first-child {
-      color: #1f1f1f;
-    }
+        color: #1f1f1f;
+      }
+
       .total-price {
         color: #ff5500;
         font-size: 32rpx;
       }
     }
   }
+
   .order-info-card {
     background: #fff;
     border-radius: 16rpx;
     margin: 24rpx 16rpx 0 16rpx;
     padding: 24rpx;
+
     .info-row {
       display: flex;
       align-items: center;
       justify-content: space-between;
       height: 56rpx;
-      font-size: 26rpx; 
-     >text:first-child {
+      font-size: 26rpx;
+
+      >text:first-child {
         color: #999;
       }
+
       .copy-btn {
         color: #1f1f1f;
         background: #f6faf6;
@@ -380,6 +569,7 @@ export default {
       }
     }
   }
+
   .order-bottom {
     position: fixed;
     left: 0;
@@ -393,6 +583,7 @@ export default {
     height: 110rpx;
     box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.04);
     z-index: 10;
+
     .btn {
       min-width: 180rpx;
       height: 72rpx;
@@ -402,29 +593,97 @@ export default {
       font-size: 30rpx;
       padding: 0 32rpx;
       margin-left: 24rpx;
+
       &.btn-pay {
         background: #1f1f1f;
         color: #acf934;
       }
+
       &.btn-cancel {
         background: #fff;
         color: #1f1f1f;
         border: 2rpx solid #e5e5e5;
       }
+
       &.btn-refund {
         background: #1f1f1f;
         color: #acf934;
       }
+
       &.btn-delete {
         background: #fff;
         color: #1f1f1f;
         border: 2rpx solid #e5e5e5;
       }
+
       &.btn-comment {
         background: #1f1f1f;
         color: #acf934;
       }
     }
   }
+
+  .payment-popup {
+    background: #fff;
+    border-radius: 24rpx 24rpx 0 0;
+    padding: 32rpx;
+
+    .popup-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 32rpx;
+
+      .popup-title {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #1f1f1f;
+      }
+    }
+
+    .payment-options {
+      .payment-option {
+        display: flex;
+        align-items: center;
+        padding: 24rpx 0;
+        border-bottom: 2rpx solid #f6faf6;
+
+        .payment-icon {
+          width: 48rpx;
+          height: 48rpx;
+          margin-right: 18rpx;
+        }
+
+        .payment-name {
+          flex: 1;
+          font-size: 30rpx;
+          color: #1f1f1f;
+        }
+
+        .payment-select {
+          width: 32rpx;
+          height: 32rpx;
+        }
+      }
+    }
+
+    .confirm-payment {
+      margin-top: 32rpx;
+      background: #1f1f1f;
+      color: #acf934;
+      border-radius: 44rpx;
+      font-size: 32rpx;
+      font-weight: bold;
+      height: 88rpx;
+      line-height: 88rpx;
+      text-align: center;
+    }
+  }
+
+  .btn-delete {
+    background: #f6faf6;
+    color: #888;
+    border: 1px solid #e5e5e5;
+  }
 }
 </style>

+ 103 - 79
pages/crowdFunding/orderList.vue

@@ -44,7 +44,7 @@
         </view>
       </scroll-view>
     </view>
-
+    <view class="tabs-reserveaseat"></view>
     <!-- Swiper订单列表 -->
     <swiper
       :current="currentTab"
@@ -137,88 +137,18 @@ export default {
         { name: "待支付", type: "waitPay" },
         { name: "已付款", type: "paid" },
         { name: "待发货", type: "waitSend" },
-        { name: "待收货", type: "waitReceive" },
+        { name: "已发货", type: "waitReceive" },
         { name: "交易完成", type: "finish" },
-        { name: "退款", type: "refund" },
+        { name: "退款", type: "refund" },
         { name: "支付失败", type: "payFail" },
       ],
-      orderList: [
-        {
-          id: 1,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "payFail",
-          statusText: "支付失败",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-        {
-          id: 2,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "waitPay",
-          statusText: "待支付",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-        {
-          id: 3,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "paid",
-          statusText: "已付款待发货",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-        {
-          id: 4,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "waitReceive",
-          statusText: "商品已发货",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-        {
-          id: 5,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "finish",
-          statusText: "交易完成",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-        {
-          id: 6,
-          projectTitle: "也许时间是一种解药",
-          isInitiator: true,
-          statusType: "refund",
-          statusText: "已退款",
-          img: "/static/crowdFunding/top-img.png",
-          title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系卡牌设计",
-          spec: "灯塔MINI版",
-          price: 389.0,
-          count: 1,
-        },
-      ],
+      orderList: [],
       swiperHeight: 600, // 默认高度,后续可动态调整
     };
   },
+  onLoad() {
+    this.getdataList();
+  },
   computed: {
     filteredOrders() {
       if (this.tabs[this.currentTab].type === "all") return this.orderList;
@@ -264,19 +194,106 @@ export default {
       });
     },
     pay(order) {
+      uni.navigateTo({
+        url: "/pages/crowdFunding/orderDetail?orderId=" + order.id,
+      });
       /* 支付逻辑 */
     },
     deleteOrder(order) {
       /* 删除逻辑 */
+       uni.navigateTo({
+        url: "/pages/crowdFunding/orderDetail?orderId=" + order.id,
+      });
     },
     cancelOrder(order) {
       /* 取消/退款逻辑 */
+       uni.navigateTo({
+        url: "/pages/crowdFunding/orderDetail?orderId=" + order.id,
+      });
     },
     confirmReceive(order) {
       /* 确认收货逻辑 */
+       uni.navigateTo({
+        url: "/pages/crowdFunding/orderDetail?orderId=" + order.id,
+      });
     },
     commentOrder(order) {
       /* 评价逻辑 */
+       uni.navigateTo({
+        url: "/pages/crowdFunding/orderDetail?orderId=" + order.id,
+      });
+    },
+    getdataList() {
+      uni.request({
+        url: this.$apiHost + '/Order/getlist?type=buyCrowdfund',
+        data:{
+          uuid: getApp().globalData.uuid,
+          skey: getApp().globalData.skey,
+        },
+        method: 'GET',
+        success: (res) => {
+          console.log(res.data.list, "获取订单");
+          this.orderList = res.data.list.map(order => {
+            let statusType = '';
+            let statusText = '';
+            switch (order.status) {
+              case 0:
+                statusType = 'waitPay';
+                statusText = '待支付';
+                break;
+              case 1:
+                statusType = 'paid';
+                statusText = '已付款待发货';
+                break;
+              case 2:
+                statusType = 'waitReceive';
+                statusText = '商品已发货';
+                break;
+              case 3:
+                statusType = 'finish';
+                statusText = '已收货';
+                break;
+              case 5:
+                statusType = 'finish';
+                statusText = '交易完成';
+                break;
+              case 6:
+                statusType = 'refund';
+                statusText = '退款中';
+                break;
+              case 8:
+                statusType = 'payFail';
+                statusText = '已关闭';
+                break;
+              case 9:
+                statusType = 'finish';
+                statusText = '已完成';
+                break;
+              default:
+                statusType = 'waitPay';
+                statusText = '待支付';
+            }
+            return {
+              ...order,
+              statusType,
+              statusText,
+              projectTitle: order.name,
+              title: order.name,
+              spec: order.name2,
+              img: order.image,
+              price: order.money,
+              count: order.num,
+              isInitiator: false
+            };
+          });
+        },
+        fail: () => {
+          uni.showToast({ title: '获取订单失败', icon: 'none' });
+        },
+        complete: () => {
+          this.updateSwiperHeight();
+        }
+      });
     },
   },
   mounted() {
@@ -346,10 +363,17 @@ export default {
       }
     }
   }
-
+  .tabs-reserveaseat{
+    width: 100vw;
+    height: 72rpx;
+  }
   .tabs-section {
     background: #fff;
-
+    position: fixed;
+    top: calc(90rpx + var(--status-bar-height));
+    left: 0;
+    border-bottom: 6rpx solid #f6faf6;
+    z-index: 100;
     .tabs-scroll-view {
       width: 100vw;
       box-sizing: border-box;

+ 61 - 29
pages/crowdFunding/receivingAddress.vue

@@ -10,18 +10,18 @@
       </view>
     </view>
 
-    <view class="address-card" v-for="item in addressList" :key="item.id">
+    <view class="address-card" v-for="item in addressList" :key="item.id" @click="selectAddress(item)" :style="isSelectAddress && selectedAddress && selectedAddress.id === item.id ? 'border-color: #000000;' : ''">
       <view class="left">
         <view class="row">
-        <text class="name">{{ item.name }}</text>
+        <text class="name">{{ item.realname }}</text>
         <text class="mobile">{{ item.mobile }}</text>
         <text class="default" v-if="item.isDefault">默认</text>
         <!-- <image class="edit" src="@/static/icon/edit.png" @click="goEdit(item)" /> -->
       </view>
-      <view class="address two-omit">{{ item.fullAddress }}</view>
+      <view class="address two-omit">{{ item.area }}</view>
       </view>
-      <view class="right">
-        <image src="@/static/icon/sy_icon_fabiao.png" @click="goEdit(item)" />
+      <view class="right" @click.stop="goEdit(item)">
+        <image src="@/static/icon/sy_icon_fabiao.png" />
       </view>
     </view>
   </view>	
@@ -31,31 +31,29 @@
 export default {
   data() {
     return {
-      addressList: [
-        {
-          id: 1,
-          name: "戴驿宸",
-          mobile: "17788196551",
-          isDefault: true,
-          fullAddress: "浙江省 杭州市 滨江区 西兴街道 启悦府",
-        },
-        {
-          id: 2,
-          name: "戴驿宸",
-          mobile: "17788196551",
-          isDefault: false,
-          fullAddress: "浙江省 杭州市 滨江区 西兴街道 启悦府",
-        },
-        {
-          id: 3,
-          name: "戴驿宸",
-          mobile: "17788196551",
-          isDefault: false,
-          fullAddress: "浙江省 杭州市 滨江区 西兴街道 启悦府",
-        },
-      ],
+      addressList: [ ],
+      isSelectAddress: false,
+      selectedAddress: null,
+      selectedSpec:null,
+      detail:null
     };
   },
+  onLoad(options) { 
+ 
+    if (options.isSelectAddress == true || options.isSelectAddress == 'true') {
+      this.isSelectAddress = true;
+      const eventChannel = this.getOpenerEventChannel();
+      eventChannel.on('acceptDataFromOpener', (data) => {
+        this.selectedSpec = data.selectedSpec;
+        this.detail = data.detail;
+        console.log('接收到的数据:', this.selectedSpec, this.detail);
+      });
+    } 
+    
+  },
+  onShow() {
+    this.getAddressList();
+  },
   methods: {
     goBack() {
       uni.navigateBack();
@@ -66,6 +64,39 @@ export default {
     goEdit(item) {
       uni.navigateTo({ url: "/pages/crowdFunding/addressEdit?id=" + item.id });
     },
+    selectAddress(item) {
+      if (this.isSelectAddress) {
+        this.selectedAddress = item; 
+        uni.navigateTo({
+				url: '/pages/crowdFunding/orderConfirm',
+				success: function(res) {
+					// 通过 eventChannel 向被打开页面传送数据
+					res.eventChannel.emit('acceptDataFromOpener', { selectedSpec: this.selectedSpec, detail: this.detail });
+
+          res.eventChannel.emit('acceptAddress', item);
+				}.bind(this)
+			});
+      }
+    },
+    getAddressList() {
+      uni.request({
+				url: this.$apiHost + '/Address/getlist',
+				method: 'GET',
+				data: {
+					id: this.projectId,
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey
+
+				},
+				success: (res) => {
+					if (res.data ) {
+            this.addressList = res.data.list;
+            console.log(this.addressList,"地址列表");
+						// 可根据接口返回字段设置isFavorite等
+					}
+				}
+			});
+    },
   },
 };
 </script>
@@ -134,6 +165,7 @@ export default {
     display: flex;
     align-items: center;
     justify-content: space-between;
+    border: 2rpx solid transparent;
     .left{
         height: 100%;
         .row {
@@ -175,7 +207,7 @@ export default {
     }
     .right{
       width: 100rpx;
-      height: 100%;
+      height: 90rpx;
       flex-shrink: 0;
       display: flex;
       align-items: center;

+ 28 - 26
pages/index/index.vue

@@ -54,7 +54,8 @@
 
 								<template #suffix>
 									<view class="input-box">
-										<image src="@/static/home/sy_icon_sousuo.png" style="width: 32rpx; height: 32rpx">
+										<image src="@/static/home/sy_icon_sousuo.png"
+											style="width: 32rpx; height: 32rpx">
 										</image>
 									</view>
 								</template>
@@ -64,31 +65,20 @@
 				</page-navbar>
 			</template>
 			<view class="benner-box" style="padding-bottom: 0;">
-				
+
 				<sortble :default-sorts="['uvSwiper', 'classModel', 'uvSwiperCard']">
 					<template #uvSwiper>
-						<uv-swiper style="border-radius: 20rpx;" :list="bannerList" keyName="image" :autoplay="true" circular :interval="5000"
-							indicator indicator-mode="dot" @click="handleBannerClick" height="116" radius="0">
+						<uv-swiper style="border-radius: 20rpx;" :list="bannerList" keyName="image" :autoplay="true"
+							circular :interval="5000" indicator indicator-mode="dot" @click="handleBannerClick"
+							height="116" radius="0">
 
 						</uv-swiper>
 					</template>
 
 					<template #classModel>
-						<view class="classModel" v-if="isTheTask">
-							<image src="@/static/home/benner-iconBom.png" class="benner-iconBom" mode=""></image>
-							<image src="@/static/home/benner-icontop.png" class="benner-icontop" mode=""></image>
-							<view class="benner-box benner-left-box" @click="goPage('/pages/my/job')">
-								<view class="text1"> 获取奖励 </view>
-								<view class="btn"> 立即前往 </view>
-							</view>
-							<view class="benner-box benner-right-box" ref="classModel1">
-								<view class="guard">
-									<view class="text"> 潮玩IP </view>
-								</view>
-								<view class="match">
-									<view class="text"> 社交 </view>
-								</view>
-							</view>
+						<view class="classModel-box">
+							<image @click="goPage('/pages/my/job')" src="@/static/home/task.png" class="benner-iconBom scale-tap" mode=""></image>
+							<image @click="goPage('/pages/crowdFunding/crowdFunding')" src="@/static/home/crowdFunding.png" class="benner-icontop scale-tap" mode=""></image>
 						</view>
 					</template>
 				</sortble>
@@ -145,7 +135,8 @@
 						<view class="explore-list">
 							<view class="hot-topics" v-if="currentTab === 2">
 								<view class="hot-topics-header">
-									<image class="hot-topics-title" src="@/static/home/hot-topics-title.png" mode="aspectFit">
+									<image class="hot-topics-title" src="@/static/home/hot-topics-title.png"
+										mode="aspectFit">
 									</image>
 								</view>
 								<swiper class="hot-topics-swiper" :current="currentTopicPage"
@@ -476,12 +467,12 @@ export default {
 				},
 				success: (res) => {
 					console.log(this.weather, "天气数据", res.data);
-					if (res&&res.data&&res.data.data.city) {
+					if (res && res.data && res.data.data.city) {
 						this.currentCity = res.data.data.city;
 						this.weather = res.data.data;
-						
+
 					}
-					if (res&&res.data&&res.data.page) {
+					if (res && res.data && res.data.page) {
 						this.goPage(res.data.page)
 					}
 				},
@@ -1041,9 +1032,9 @@ export default {
 			}, 300);
 		},
 		handleBannerClick(index) {
-			
+
 			const item = this.bannerList[index];
-			console.log(111,index,item);
+			console.log(111, index, item);
 			if (item && item.url) {
 				uni.navigateTo({
 					url: item.url
@@ -1094,7 +1085,18 @@ export default {
 .explore-list {
 	min-height: 300px;
 }
+.classModel-box{
+	width: 100%;
+ 
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	image{
+		width:50%;
+		height:160rpx;
+	} 
+}
 </style>
 <style>
-@import "@/style/qweather-icons.css"; 
+@import "@/style/qweather-icons.css";
 </style>

+ 2 - 2
pages/make/index.vue

@@ -15,9 +15,9 @@
 					<text>{{ myinfo.num_gmd | formatNumberToK }}</text>
 					<image class="money-add" v-if="isRecharge" src="/static/icon/coin_add.png" mode="aspectFit"></image>
 				</view>
-
+<!-- 
 				<image style="width: 64rpx ; height: 64rpx;" src="/static/icon/renwu.png" mode="aspectFit"
-					@click="goPage('/pages/my/job')"></image>
+					@click="goPage('/pages/my/job')"></image> -->
 
 			</view>
 		</view>

+ 46 - 43
pages/message/mailMessage.vue

@@ -100,18 +100,24 @@
 			<template v-if="true || offset">
 				<block v-for="(item, index) in list3" :key="index">
 					<view class="msg-card"   @click="goPages('/pages/crowdFunding/customerService?id='+item.id)">
-						<image class="avatar" :src="item.avatar" />
+						<image class="avatar" :src="item&&item.kefu_info&&item.kefu_info.avatar" />
 						<view class="msg-main">
 							<view class="msg-header">
-								<text class="nickname">{{ item.nickname }}</text>
-								<text class="tag" v-if="item.tag">{{ item.tag }}</text>
+								<text class="nickname">{{ item&&item.kefu_info&&item.kefu_info.nickname }}</text>
+								<text class="tag"  > 发起人</text>
 								<text class="time">{{ item.create_time }}</text>
 							</view>
-							<view class="msg-content">{{ item.content }}</view>
+							<view class="msg-content">{{ item.last_message }}</view>
 						</view>
-						<view v-if="item.quantity >0" class="red-dot">{{ item.quantity }}</view>
+						<view v-if="item.unread_count >0" class="red-dot">{{ item.unread_count }}</view>
 					</view>
 				</block>
+					<!-- avatar: '../../static/home/avator.png',
+					nickname: '雾里',
+					tag: '发起人',
+					create_time: '17:10',
+					content: '谢谢你的关注,远方的陌生人',
+					quantity: 1	 -->
 				<view class="blankHeight"></view>
 				<view class="loading-more" v-if="tab === 3">
 					<text v-if="isLoading">正在加载更多...</text>
@@ -175,54 +181,21 @@ export default {
 				1: "sms",
 				2: "hudong",
 			},
-			list3: [
-				{
-					avatar: '../../static/home/avator.png',
-					nickname: '雾里',
-					tag: '发起人',
-					create_time: '17:10',
-					content: '谢谢你的关注,远方的陌生人',
-					quantity: 1	
-				},{
-					avatar: '../../static/home/avator.png',
-					nickname: '雾里',
-					tag: '发起人',
-					create_time: '17:10',
-					content: '谢谢你的关注,远方的陌生人',
-					quantity: 0	
-				},{
-					avatar: '../../static/home/avator.png',
-					nickname: '雾里',
-					tag: '发起人',
-					create_time: '17:10',
-					content: '谢谢你的关注,远方的陌生人',
-					quantity: 9	
-				},
-			],  
-		};
-	},
-	onLoad() {
-		this.loadData();
-	},
-	onShow() {
-		this.refreshData();
-	},
-	onPullDownRefresh() {
-		this.refreshData();
-	},
-	onReachBottom() {
-		if (this.hasMore && !this.isLoading) {
-			this.loadMore();
+			list3: [ 
+			],
 		};
 	},
 	onLoad() {
 		this.loadData();
+		this.getKefuConversations();
 	},
 	onShow() {
 		this.refreshData();
+		this.getKefuConversations();
 	},
 	onPullDownRefresh() {
 		this.refreshData();
+		this.getKefuConversations();
 	},
 	onReachBottom() {
 		if (this.hasMore && !this.isLoading) {
@@ -237,6 +210,7 @@ export default {
 		}
 	},
 	methods: {
+		
 		 goPages(url){
 			console.log(url, 'url');
 			
@@ -248,6 +222,9 @@ export default {
 		checkTab(tab) {
 			this.tab = tab;
 			this.refreshData();
+			if (tab === 3) {
+				this.getKefuConversations();
+			}
 		},
 		scroll: function (e) {
 			console.log(e);
@@ -382,6 +359,32 @@ export default {
 				return url.split("|")[0];
 			}
 		},
+		getKefuConversations() {
+			uni.request({
+				url: this.$apiHost + '/App/kefuGetConversations',
+				method: 'GET',
+				data: {
+					uuid: getApp().globalData.uuid,
+					skey: getApp().globalData.skey
+				},
+				success: (res) => {
+					console.log(res.data, "获取客服消息列表");
+					if (res.data && res.data.success == 'yes') {
+						this.list3 = res.data.data.conversations || [];
+						console.log(res.data.data.conversations, "获取客服消息列表");
+						
+					} else {
+						uni.showToast({ title: res.data.message || '获取客服消息失败', icon: 'none' });
+					}
+				},
+				fail: () => {
+					uni.showToast({ title: '获取客服消息失败', icon: 'none' });
+				},
+				complete: () => {
+					uni.stopPullDownRefresh();
+				}
+			});
+		},
 	},
 };
 </script>

+ 205 - 0
pages/my/creativeExpert.vue

@@ -0,0 +1,205 @@
+<template>
+	<view class="creative-expert-page">
+		<!-- 等级进度 -->
+		<view class="level-progress-section">
+			<view class="current-level">
+				<image class="level-icon" src="/static/creative/level1.png" />
+				<text class="level-text">Lv.1</text>
+			</view>
+			<view class="exp-bar-wrap">
+				<view class="exp-bar-bg">
+					<view class="exp-bar" :style="{ width: '20%' }"></view>
+				</view>
+				<view class="exp-info">
+					升级到下个等级还需
+					<text class="exp-num">280</text>点经验
+				</view>
+			</view>
+			<view class="level-labels">
+				<text class="level-label">Lv.1</text>
+				<text class="level-label next">Lv.2</text>
+			</view>
+			<view class="join-btn">会员加速中</view>
+		</view>
+
+		<!-- 创意达人值说明 -->
+		<view class="section-title">创意达人值说明</view>
+		<view class="desc-block">
+			创意达人值是萌创星球给用户提供的一个创意设计等级认证说明,代表着用户运营型社团创作能力的直观体现。
+			<view class="desc-tip">在达标属于摸索力和创造力的环节上,每一个闪光的方案都值得被看见,每一次大胆的尝试都值得被徽章收藏。</view>
+			星球的星灵们会根据您的作品数量、作品点赞数、作品评论数、未展示及在作一作品的数量等多维度作为创意达人值的考核标准。
+			创意达人值越高,创意达人等级也会越高,不同的创意达人等级会获得专属徽标和权益。每个等级都有自己的专属徽标和权益。
+		</view>
+
+		<!-- 等级表格 -->
+		<view class="section-title">创意达人等级专属徽标&等级</view>
+		<view class="level-table">
+			<view class="table-header">
+				<view class="th">对应展示</view>
+				<view class="th">等级</view>
+				<view class="th">活跃值</view>
+			</view>
+			<view class="table-row" v-for="row in levelRows" :key="row.level">
+				<view class="td">
+					<image :src="row.icon" class="level-table-icon" />
+				</view>
+				<view class="td">{{ row.level }}</view>
+				<view class="td">{{ row.active }}</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				levelRows: [
+					{ icon: '/static/creative/level1.png', level: 'Lv.1', active: '未解锁' },
+					{ icon: '/static/creative/level2.png', level: 'Lv.2', active: '未解锁' },
+					{ icon: '/static/creative/level3.png', level: 'Lv.3', active: '未解锁' },
+					{ icon: '/static/creative/level4.png', level: 'Lv.4', active: '未解锁' },
+					{ icon: '/static/creative/level5.png', level: 'Lv.5', active: '未解锁' },
+				]
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style scoped>
+.creative-expert-page {
+	background: #181a1f;
+	min-height: 100vh;
+	color: #fff;
+	padding-bottom: 40rpx;
+}
+.level-progress-section {
+	background: #23242a;
+	border-radius: 0 0 32rpx 32rpx;
+	padding: 48rpx 32rpx 32rpx 32rpx;
+	text-align: center;
+	position: relative;
+}
+.current-level {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	margin-bottom: 16rpx;
+}
+.level-icon {
+	width: 80rpx;
+	height: 80rpx;
+	margin-right: 12rpx;
+}
+.level-text {
+	font-size: 36rpx;
+	font-weight: bold;
+	color: #ffb86c;
+}
+.exp-bar-wrap {
+	margin: 24rpx 0 8rpx 0;
+}
+.exp-bar-bg {
+	width: 100%;
+	height: 16rpx;
+	background: #2d2e36;
+	border-radius: 8rpx;
+	overflow: hidden;
+}
+.exp-bar {
+	height: 100%;
+	background: linear-gradient(90deg, #ffb86c 0%, #ffe7b2 100%);
+	border-radius: 8rpx;
+}
+.exp-info {
+	font-size: 24rpx;
+	color: #fff;
+	margin-top: 8rpx;
+}
+.exp-num {
+	color: #ffb86c;
+	font-weight: bold;
+}
+.level-labels {
+	display: flex;
+	justify-content: space-between;
+	margin-top: 8rpx;
+}
+.level-label {
+	font-size: 24rpx;
+	color: #ffb86c;
+}
+.level-label.next {
+	color: #fff;
+}
+.join-btn {
+	margin: 24rpx auto 0 auto;
+	width: 320rpx;
+	height: 56rpx;
+	background: linear-gradient(90deg, #ffb86c 0%, #ffe7b2 100%);
+	color: #23242a;
+	border-radius: 32rpx;
+	font-size: 28rpx;
+	font-weight: bold;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+.section-title {
+	font-size: 30rpx;
+	font-weight: bold;
+	color: #ffb86c;
+	margin: 40rpx 0 16rpx 32rpx;
+}
+.desc-block {
+	background: #23242a;
+	border-radius: 24rpx;
+	margin: 0 32rpx;
+	padding: 32rpx 24rpx;
+	font-size: 26rpx;
+	color: #fff;
+	line-height: 1.8;
+}
+.desc-tip {
+	color: #ffe7b2;
+	margin: 16rpx 0;
+	font-size: 26rpx;
+}
+.level-table {
+	background: #23242a;
+	border-radius: 24rpx;
+	margin: 0 32rpx;
+	margin-top: 24rpx;
+	padding: 24rpx 0;
+}
+.table-header, .table-row {
+	display: flex;
+	align-items: center;
+	padding: 0 24rpx;
+}
+.table-header {
+	font-size: 26rpx;
+	color: #ffe7b2;
+	font-weight: bold;
+	border-bottom: 2rpx solid #2d2e36;
+	height: 60rpx;
+}
+.th, .td {
+	flex: 1;
+	text-align: center;
+}
+.level-table-icon {
+	width: 56rpx;
+	height: 56rpx;
+	vertical-align: middle;
+}
+.table-row {
+	font-size: 26rpx;
+	color: #fff;
+	height: 72rpx;
+	border-bottom: 1rpx solid #23242a;
+}
+</style>

TEMPAT SAMPAH
static/home/crowdFunding.png


TEMPAT SAMPAH
static/home/task.png