diff --git a/components/goods-card/goods-card.js b/components/goods-card/goods-card.js
new file mode 100644
index 0000000..1ad8696
--- /dev/null
+++ b/components/goods-card/goods-card.js
@@ -0,0 +1,43 @@
+Component({
+ properties: {
+ id: { type: String, value: '' },
+ name: { type: String, value: '' },
+ imageUrl: { type: String, value: '' },
+ price: { type: [String, Number], value: '' },
+ priceUnit: { type: String, value: '/件' },
+ region: { type: String, value: '' },
+ specification: { type: String, value: '' },
+ spec: { type: String, value: '' },
+ specs: { type: String, value: '' },
+ displaySpecification: { type: String, value: '' },
+ displayYolk: { type: String, value: '' },
+ sourceType: { type: String, value: '' },
+ totalStock: { type: [String, Number], value: '' },
+ supplyStatus: { type: String, value: '' },
+ status: { type: String, value: '' },
+ reservedCount: { type: [String, Number], value: 0 }
+ },
+
+ data: {
+ isSoldOut: false
+ },
+
+ observers: {
+ 'status': function(status) {
+ this.setData({
+ isSoldOut: status === 'sold_out'
+ });
+ }
+ },
+
+ methods: {
+ onTap: function() {
+ const goodsId = this.properties.id;
+ if (goodsId) {
+ wx.navigateTo({
+ url: `/pages/goods-detail/goods-detail?id=${goodsId}`
+ });
+ }
+ }
+ }
+});
diff --git a/components/goods-card/goods-card.json b/components/goods-card/goods-card.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/components/goods-card/goods-card.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/components/goods-card/goods-card.wxml b/components/goods-card/goods-card.wxml
new file mode 100644
index 0000000..26db4ae
--- /dev/null
+++ b/components/goods-card/goods-card.wxml
@@ -0,0 +1,33 @@
+
+
+
+
+ 暂无图片
+
+ 预售
+ 现货
+ 售空
+
+
+ {{name || '商品名称'}}
+ {{displaySpecification}}{{displayYolk ? ' | ' + displayYolk : ''}}
+
+ {{sourceType || ''}}
+ 库存:{{totalStock && totalStock !== '充足' ? totalStock + '件' : (totalStock || '充足')}}
+
+
+
+ ¥
+ {{price || '0'}}
+ {{priceUnit || '/件'}}
+
+ {{region || ''}}
+
+
+
diff --git a/components/goods-card/goods-card.wxss b/components/goods-card/goods-card.wxss
new file mode 100644
index 0000000..e203bd5
--- /dev/null
+++ b/components/goods-card/goods-card.wxss
@@ -0,0 +1,159 @@
+.goods-card {
+ width: 100%;
+ max-width: 560rpx;
+ background: #fff;
+ border-radius: 16rpx;
+ overflow: hidden;
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
+ display: flex;
+ flex-direction: column;
+}
+
+.goods-card.sold-out {
+ opacity: 0.7;
+}
+
+.goods-image-area {
+ position: relative;
+ width: 100%;
+ height: 280rpx;
+ background: #f5f5f5;
+}
+
+.goods-image {
+ width: 100%;
+ height: 100%;
+ display: block;
+ object-fit: cover;
+}
+
+.goods-image-placeholder {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #f0f0f0;
+ color: #999;
+ font-size: 24rpx;
+}
+
+.promo-tag {
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: 6rpx 12rpx;
+ font-size: 20rpx;
+ color: #fff;
+ border-radius: 0 0 12rpx 0;
+ z-index: 1;
+ font-weight: 600;
+}
+
+.promo-tag.presale {
+ background: linear-gradient(135deg, #ff6b00 0%, #ff8c00 100%);
+}
+
+.promo-tag.in-stock {
+ background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
+}
+
+.promo-tag.sold-out {
+ background: linear-gradient(135deg, #a92a2a 0%, #a6a6a6 100%);
+}
+
+.goods-info {
+ padding: 16rpx;
+ display: flex;
+ flex-direction: column;
+ gap: 8rpx;
+}
+
+.goods-title {
+ font-size: 26rpx;
+ color: #000000;
+ line-height: 1.4;
+ height: 72rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ font-weight: 700;
+}
+
+.goods-spec {
+ font-size: 22rpx;
+ color: #666;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.goods-tags {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center;
+ gap: 8rpx;
+ margin: 6rpx 0;
+}
+
+.tag {
+ font-size: 20rpx;
+ padding: 4rpx 10rpx;
+ border-radius: 6rpx;
+}
+
+.tag.source-third {
+ background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
+ color: #fff;
+}
+
+.tag.source-platform {
+ background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
+ color: #fff;
+}
+
+.tag.source-unverified {
+ background: rgba(0, 0, 0, 0.08);
+ color: #666;
+}
+
+.tag.stock {
+ background: rgba(255, 77, 79, 0.08);
+ color: #666;
+}
+
+.goods-bottom {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ margin-top: 6rpx;
+}
+
+.goods-price {
+ display: flex;
+ align-items: baseline;
+}
+
+.price-unit {
+ font-size: 24rpx;
+ color: #ff4d4f;
+ font-weight: 700;
+}
+
+.price-value {
+ font-size: 36rpx;
+ color: #ff4d4f;
+ font-weight: 800;
+ margin: 0 2rpx;
+}
+
+.goods-region {
+ font-size: 20rpx;
+ color: #999;
+ max-width: 100rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/pages/chat-detail/index.js b/pages/chat-detail/index.js
index abe1a97..b37b602 100644
--- a/pages/chat-detail/index.js
+++ b/pages/chat-detail/index.js
@@ -172,9 +172,25 @@ Page({
const processedMessages = res.map(message => {
const sender = (message.sender_phone === userPhone) ? 'me' : 'other';
const time = this.formatDateTime(message.created_at);
+
+ // 尝试解析JSON格式的商品消息
+ let content = message.content;
+ let goodsData = null;
+
+ try {
+ const parsed = JSON.parse(message.content);
+ if (parsed.type === 'goods' && parsed.goodsData) {
+ goodsData = parsed.goodsData;
+ content = parsed.text || '';
+ }
+ } catch (e) {
+ // 不是JSON格式,使用原始内容
+ }
+
return {
id: message.id,
- content: message.content,
+ content: content,
+ goodsData: goodsData,
sender: sender,
time: time,
originalTime: message.created_at,
diff --git a/pages/chat-detail/index.json b/pages/chat-detail/index.json
index 796c826..79cf89c 100644
--- a/pages/chat-detail/index.json
+++ b/pages/chat-detail/index.json
@@ -1,3 +1,6 @@
{
- "navigationBarTitleText": "聊天详情"
+ "navigationBarTitleText": "聊天详情",
+ "usingComponents": {
+ "goods-card": "/components/goods-card/goods-card"
+ }
}
\ No newline at end of file
diff --git a/pages/chat-detail/index.wxml b/pages/chat-detail/index.wxml
index e7c0edf..5dd5bc1 100644
--- a/pages/chat-detail/index.wxml
+++ b/pages/chat-detail/index.wxml
@@ -28,7 +28,24 @@
- {{item.content}}
+
+
+
+
+
+ {{item.content}}
{{item.time}}
diff --git a/pages/chat-detail/index.wxss b/pages/chat-detail/index.wxss
index 96571c1..b31d79d 100644
--- a/pages/chat-detail/index.wxss
+++ b/pages/chat-detail/index.wxss
@@ -233,4 +233,54 @@
.send-button:hover {
background-color: #FF526D;
+}
+
+/* 商品消息卡片样式 */
+.goods-message-card {
+ width: 100%;
+ min-width: 280rpx;
+ max-width: 400rpx;
+}
+
+.goods-message-card .goods-card {
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
+}
+
+/* 商品卡片在小消息气泡中的适配 */
+.message-item .message-bubble {
+ padding: 12rpx;
+}
+
+.goods-message-card .goods-image-area {
+ height: 200rpx;
+}
+
+.goods-message-card .goods-info {
+ padding: 12rpx;
+}
+
+.goods-message-card .goods-title {
+ font-size: 24rpx;
+ height: 66rpx;
+}
+
+.goods-message-card .goods-spec {
+ font-size: 20rpx;
+}
+
+.goods-message-card .goods-tags {
+ margin: 4rpx 0;
+}
+
+.goods-message-card .tag {
+ font-size: 18rpx;
+ padding: 2rpx 6rpx;
+}
+
+.goods-message-card .price-value {
+ font-size: 32rpx;
+}
+
+.goods-message-card .price-unit {
+ font-size: 22rpx;
}
\ No newline at end of file
diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js
index 1ebc8bc..3d92fff 100644
--- a/pages/goods-detail/goods-detail.js
+++ b/pages/goods-detail/goods-detail.js
@@ -81,6 +81,92 @@ function formatShareTitle(goodsDetail) {
return goodsDetail.name ? `优质鸡蛋 - ${goodsDetail.name}` : '优质鸡蛋货源';
}
+// 构建商品分享消息内容
+function buildShareGoodsMessage(goodsDetail) {
+ const parts = [];
+
+ // 商品名称
+ if (goodsDetail.name) {
+ parts.push(`【商品】${goodsDetail.name}`);
+ }
+
+ // 规格
+ const specification = (goodsDetail.specification || goodsDetail.spec || goodsDetail.specs || '').trim();
+ if (specification) {
+ parts.push(`【规格】${specification}`);
+ }
+
+ // 地区
+ const region = (goodsDetail.region || '').trim();
+ if (region) {
+ parts.push(`【地区】${region}`);
+ }
+
+ // 数量
+ const quantity = (goodsDetail.quantity || '').trim();
+ if (quantity) {
+ parts.push(`【数量】${quantity}`);
+ }
+
+ // 价格
+ if (goodsDetail.price) {
+ parts.push(`【价格】${goodsDetail.price}`);
+ }
+
+ // 货源类型
+ const sourceType = (goodsDetail.sourceType || '').trim();
+ if (sourceType) {
+ parts.push(`【货源】${sourceType}`);
+ }
+
+ // 联系人
+ if (goodsDetail.product_contact) {
+ parts.push(`【联系人】${goodsDetail.product_contact}`);
+ }
+
+ // 联系电话
+ if (goodsDetail.contact_phone) {
+ parts.push(`【电话】${goodsDetail.contact_phone}`);
+ }
+
+ // 蛋黄颜色
+ const yolk = (goodsDetail.yolk || '').trim();
+ if (yolk) {
+ parts.push(`【蛋黄】${yolk}`);
+ }
+
+ // 蛋壳颜色/品种
+ const eggshell = (goodsDetail.eggshell || goodsDetail.shell || goodsDetail.breed || '').trim();
+ if (eggshell) {
+ parts.push(`【蛋壳/品种】${eggshell}`);
+ }
+
+ // 新鲜程度
+ const freshness = (goodsDetail.freshness || '').trim();
+ if (freshness) {
+ parts.push(`【新鲜程度】${freshness}`);
+ }
+
+ // 备注描述
+ const description = (goodsDetail.description || '').trim();
+ if (description) {
+ parts.push(`【备注】${description}`);
+ }
+
+ // 获取第一张图片作为商品图片
+ const imageUrls = goodsDetail.imageUrls || [];
+ const firstImage = imageUrls.find(url => !isVideoUrl(url));
+
+ let message = parts.join('\n');
+
+ // 如果有图片,添加图片链接
+ if (firstImage) {
+ message += `\n\n【商品图片】${firstImage}`;
+ }
+
+ return message;
+}
+
// 获取适合分享的图片 - 优先使用正方形图片填满分享框
function getShareImageUrl(goodsDetail) {
const imageUrls = goodsDetail.imageUrls || [];
@@ -1379,19 +1465,68 @@ Page({
// 使用联系人手机号作为聊天会话ID
const chatSessionId = contactPhone;
- // 跳转到聊天页面,确保正确传递联系人手机号和用户名
- wx.navigateTo({
- url: `/pages/chat-detail/index?userId=${chatSessionId}&userName=${encodeURIComponent(contactName || '联系人')}&phone=${contactPhone}&isManager=true`,
- success: function () {
- console.log('成功跳转到聊天详情页');
- },
- fail: function (error) {
- console.error('跳转到聊天详情页失败:', error);
- wx.showToast({
- title: '聊天功能开发中',
- icon: 'none'
- });
- }
+ // 构建商品分享消息内容(包含显示文本和结构化数据)
+ const goodsDetail = this.data.goodsDetail;
+
+ // 构建结构化的商品消息
+ const goodsData = {
+ id: goodsDetail.id || '',
+ name: goodsDetail.name || '',
+ imageUrl: (goodsDetail.imageUrls && goodsDetail.imageUrls.length > 0) ?
+ (goodsDetail.imageUrls.find(url => !isVideoUrl(url)) || '') : '',
+ price: goodsDetail.price || '',
+ region: goodsDetail.region || '',
+ displaySpecification: goodsDetail.displaySpecification || goodsDetail.specification || goodsDetail.spec || goodsDetail.specs || '',
+ displayYolk: goodsDetail.displayYolk || goodsDetail.yolk || '',
+ sourceType: goodsDetail.sourceType || '',
+ totalStock: goodsDetail.totalStock || goodsDetail.stock || '',
+ supplyStatus: goodsDetail.supplyStatus || goodsDetail.status === 'sold_out' ? '' : (goodsDetail.supplyStatus || ''),
+ status: goodsDetail.status || ''
+ };
+
+ // 构建显示文本(兼容旧版本)
+ const displayText = buildShareGoodsMessage(goodsDetail);
+
+ // 发送结构化商品消息(JSON格式,包含goodsData用于展示卡片)
+ const structuredMessage = JSON.stringify({
+ type: 'goods',
+ text: displayText,
+ goodsData: goodsData
+ });
+
+ // 发送商品分享消息
+ API.sendMessage(userPhone, contactPhone, structuredMessage).then(sendRes => {
+ console.log('商品分享消息发送成功:', sendRes);
+ // 跳转到聊天页面
+ wx.navigateTo({
+ url: `/pages/chat-detail/index?userId=${chatSessionId}&userName=${encodeURIComponent(contactName || '联系人')}&phone=${contactPhone}&isManager=true`,
+ success: function () {
+ console.log('成功跳转到聊天详情页');
+ },
+ fail: function (error) {
+ console.error('跳转到聊天详情页失败:', error);
+ wx.showToast({
+ title: '聊天功能开发中',
+ icon: 'none'
+ });
+ }
+ });
+ }).catch(sendErr => {
+ console.error('发送商品分享消息失败:', sendErr);
+ // 即使发送消息失败,也跳转到聊天页面
+ wx.navigateTo({
+ url: `/pages/chat-detail/index?userId=${chatSessionId}&userName=${encodeURIComponent(contactName || '联系人')}&phone=${contactPhone}&isManager=true`,
+ success: function () {
+ console.log('成功跳转到聊天详情页');
+ },
+ fail: function (error) {
+ console.error('跳转到聊天详情页失败:', error);
+ wx.showToast({
+ title: '聊天功能开发中',
+ icon: 'none'
+ });
+ }
+ });
});
}).catch(err => {
console.error('建立聊天失败:', err);