Compare commits
13 Commits
3b31071e13
...
dbae8b4a5a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbae8b4a5a | ||
|
|
9b6a3c9bce | ||
|
|
088891bdbb | ||
|
|
e20e9a3552 | ||
|
|
8a4b3d9f69 | ||
|
|
d6b758a6bc | ||
|
|
b37a945e42 | ||
|
|
60ad675362 | ||
|
|
9083312649 | ||
|
|
cc7215d836 | ||
|
|
da59430dd9 | ||
|
|
2b90922cc3 | ||
|
|
d4c774522e |
@ -21,4 +21,7 @@ export const apiArr = {
|
||||
|
||||
goodsSearch: '/api/v2/wechat/commodity/search', // 商品搜索
|
||||
cancelPay: '/api/v2/wechat/commodity/order/cancel_pay', // 用户取消支付
|
||||
|
||||
|
||||
adverGoodsList: '/api/v2/wechat/commodity/adver-goods-list', // 广告货品列表
|
||||
}
|
||||
33
package-lock.json
generated
33
package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "1.0.1",
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"mqtt": "^3.0.0",
|
||||
"vue": "^3.5.21"
|
||||
}
|
||||
@ -220,6 +221,30 @@
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bl/node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/bl/node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
@ -245,9 +270,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -265,7 +290,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"mqtt": "^3.0.0",
|
||||
"vue": "^3.5.21"
|
||||
}
|
||||
|
||||
@ -4,88 +4,27 @@
|
||||
<view class="goods-list">
|
||||
<!-- 商品项 -->
|
||||
<view v-for="(item, index) in goodsList" :key="index">
|
||||
<!-- 有多个货品 -->
|
||||
<view class="goods-item" v-if="item.group_buy_goods_list.length > 1">
|
||||
<view class="goods-image">
|
||||
<image :src="item.commodity_pic" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ item.commodity_name }}</view>
|
||||
<view class="goods-desc">{{ item.commodity_intro }}</view>
|
||||
<view class="goods-price"> {{ getPriceRange(item.group_buy_goods_list) }} </view>
|
||||
|
||||
<!-- 选择规格标签 -->
|
||||
<view class="specification-tag" @click.stop="toggleSkuList(index)">
|
||||
<text>{{ item.showSkuList ? '收起' : '选择规格' }}</text>
|
||||
<u-icon name="arrow-down" size="26rpx" color="#FF370B" v-if="!item.showSkuList"></u-icon>
|
||||
<u-icon name="arrow-up" size="26rpx" color="#FF370B" v-else></u-icon>
|
||||
</view>
|
||||
|
||||
<!-- 货品列表 -->
|
||||
<view class="sku-list" v-if="item.showSkuList">
|
||||
<view v-for="(sku, skuIndex) in item.group_buy_goods_list" :key="skuIndex">
|
||||
<view class="sku-item" @click="toDetail(sku)">
|
||||
<view class="sku-info">
|
||||
<view class="sku-image">
|
||||
<image :src="sku.commodity_pic" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ sku.goods_name }}</view>
|
||||
<view class="goods-desc">{{ sku.goods_spec }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="price-container">
|
||||
<view class="sku-price">
|
||||
<view class="sku-price1">团购价</view>
|
||||
<view class="sku-price2">¥{{ sku.group_buy_price }}/{{ sku.goods_unit }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="sku-control">
|
||||
<view class="decrease-btn" @tap.stop="decreaseQuantity(index, skuIndex)">-
|
||||
</view>
|
||||
<view class="quantity">{{ sku.quantity }}</view>
|
||||
<view class="increase-btn" @tap.stop="increaseQuantity(index, skuIndex)">+
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="original-price">单买价 ¥{{ sku.sales_price }}/{{ sku.goods_unit }}</view>
|
||||
<view class="sku-countdown">
|
||||
{{
|
||||
getEndTheCountdown(sku.group_buy_activity_info.end_time)
|
||||
}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 只有一个货品 -->
|
||||
<view v-else>
|
||||
<view>
|
||||
<view class="goods-item2" @click="toDetail(item)">
|
||||
<view class="goods-image">
|
||||
<image :src="item.commodity_pic" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ item.commodity_name }}</view>
|
||||
<view class="goods-desc">{{ item.commodity_intro }}</view>
|
||||
<view class="goods-name">{{ item.goods_name }}</view>
|
||||
<view class="goods-desc">{{ item.goods_spec }}</view>
|
||||
<view class="price-container">
|
||||
<view class="group-price">
|
||||
<view class="group-price1">团购价</view>
|
||||
<view class="group-price2">¥{{ item.group_buy_goods_list[0].group_buy_price }}/{{
|
||||
item.group_buy_goods_list[0].goods_unit }}</view>
|
||||
<view class="group-price1">活动价</view>
|
||||
<view class="group-price2">¥{{ item.promotional_price }}/{{ item.goods_unit }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="quantity-control">
|
||||
<view class="decrease-btn" @tap.stop="decreaseQuantity(index, 0)">-</view>
|
||||
<view class="quantity">{{ item.group_buy_goods_list[0].quantity }}</view>
|
||||
<view class="increase-btn" @tap.stop="increaseQuantity(index, 0)">+</view>
|
||||
<view class="decrease-btn" @tap.stop="decreaseQuantity(index)">-</view>
|
||||
<view class="quantity">{{ item.quantity }}</view>
|
||||
<view class="increase-btn" @tap.stop="increaseQuantity(index)">+</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="original-price">单买价 ¥{{ item.group_buy_goods_list[0].sales_price }}/{{
|
||||
item.group_buy_goods_list[0].goods_unit }}</view>
|
||||
<view class="countdown">
|
||||
{{ getEndTheCountdown(item.group_buy_goods_list[0].group_buy_activity_info.end_time) }}
|
||||
</view>
|
||||
<view class="original-price">零售价 ¥{{ item.retail_price }}/{{ item.goods_unit }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -115,10 +54,12 @@ export default {
|
||||
timer: null, // 定时器ID
|
||||
endTime: '', // 初始化结束时间
|
||||
updateTime: Date.now(), // 用于触发倒计时更新的时间戳
|
||||
goodsDetail: []
|
||||
goodsDetail: [],
|
||||
idVal: '',
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
onLoad(options) {
|
||||
this.idVal = Number(options.id)
|
||||
// this.getGoodsList()
|
||||
},
|
||||
onShow() {
|
||||
@ -142,7 +83,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getGoodsList() {
|
||||
if(!uni.getStorageSync('userId')){
|
||||
if (!uni.getStorageSync('userId')) {
|
||||
uni.showToast({
|
||||
title: '请先登录',
|
||||
icon: 'none'
|
||||
@ -150,21 +91,15 @@ export default {
|
||||
return
|
||||
}
|
||||
const params = {
|
||||
user_id: uni.getStorageSync('userId')
|
||||
adver_id: this.idVal,
|
||||
}
|
||||
return request(apiArr.groupBuyList, 'POST', params).then(res => {
|
||||
const list = res.group_buy_list.map(item => {
|
||||
// 为每个货品初始化quantity
|
||||
const group_buy_goods_list = item.group_buy_goods_list.map(sku => ({
|
||||
...sku,
|
||||
commodity_pic: picUrl + sku.commodity_pic,
|
||||
quantity: 0
|
||||
}));
|
||||
return request(shopApi.adverGoodsList, 'POST', params).then(res => {
|
||||
const list = res.adver_goods_list.map(item => {
|
||||
// 为每个商品初始化quantity
|
||||
return {
|
||||
...item,
|
||||
commodity_pic: picUrl + item.commodity_pic,
|
||||
showSkuList: false,
|
||||
group_buy_goods_list
|
||||
commodity_pic: picUrl + item.goods_pic,
|
||||
quantity: 0
|
||||
}
|
||||
})
|
||||
this.goodsList = list
|
||||
@ -173,7 +108,7 @@ export default {
|
||||
},
|
||||
getShopdetail() {
|
||||
const params = {
|
||||
is_group_buy: 1,
|
||||
is_adver: 1,
|
||||
}
|
||||
return request(shopApi.getCar, "POST", params).then((res) => {
|
||||
this.carNum = res.total;
|
||||
@ -187,95 +122,82 @@ export default {
|
||||
if (!this.goodsDetail || !this.goodsList || this.goodsList.length === 0) {
|
||||
return;
|
||||
}
|
||||
// 遍历所有商品
|
||||
// 遍历所有商品,直接对item进行处理
|
||||
this.goodsList.forEach(goods => {
|
||||
// 遍历商品的所有货品
|
||||
goods.group_buy_goods_list.forEach(sku => {
|
||||
// 在购物车数据中查找对应的货品
|
||||
const matchedItem = this.goodsDetail.find(item => item.goods_id === sku.goods_id);
|
||||
// 在购物车数据中查找对应的商品
|
||||
const matchedItem = this.goodsDetail.find(item => item.goods_id === goods.goods_id);
|
||||
|
||||
// 如果找到匹配项,更新quantity
|
||||
if (matchedItem) {
|
||||
sku.quantity = matchedItem.count;
|
||||
goods.quantity = matchedItem.count;
|
||||
} else {
|
||||
// 如果没有找到,设置为0
|
||||
sku.quantity = 0;
|
||||
goods.quantity = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
toDetail(itemObj) {
|
||||
const item = {
|
||||
...itemObj,
|
||||
groupById: itemObj.group_buy_activity_info.id
|
||||
};
|
||||
NavgateTo(`/packages/shop/groupPurchaseDetail/index?item=${JSON.stringify(item)}`)
|
||||
// const item = {
|
||||
// ...itemObj,
|
||||
// groupById: itemObj.group_buy_activity_info ? itemObj.group_buy_activity_info.id : ''
|
||||
// };
|
||||
// NavgateTo(`/packages/shop/groupPurchaseDetail/index?item=${JSON.stringify(item)}`)
|
||||
},
|
||||
// 获取商品价格范围
|
||||
getPriceRange(goodsList) {
|
||||
if (!goodsList || goodsList.length === 0) return '¥0';
|
||||
const prices = goodsList.map(item => Number(item.sales_price));
|
||||
const minPrice = Math.min(...prices);
|
||||
const maxPrice = Math.max(...prices);
|
||||
return minPrice === maxPrice ? `¥${minPrice}` : `¥${minPrice} ~ ¥${maxPrice}`;
|
||||
},
|
||||
// 展开/收起货品列表
|
||||
toggleSkuList(index) {
|
||||
this.goodsList[index].showSkuList = !this.goodsList[index].showSkuList;
|
||||
},
|
||||
// 增加货品数量
|
||||
increaseQuantity(goodsIndex, skuIndex) {
|
||||
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity == 0) {
|
||||
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity += this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].min_order_quantity
|
||||
this.carNum += this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].min_order_quantity
|
||||
// 增加商品数量
|
||||
increaseQuantity(index) {
|
||||
const item = this.goodsList[index]
|
||||
if (item.quantity == 0) {
|
||||
item.quantity += item.min_order_quantity || 1
|
||||
this.carNum += item.min_order_quantity || 1
|
||||
} else {
|
||||
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity == this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].total_stock) {
|
||||
if (item.quantity == item.total_stock) {
|
||||
uni.showToast({
|
||||
title: '库存不足',
|
||||
icon: 'none'
|
||||
});
|
||||
return
|
||||
}
|
||||
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity == this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].max_limit_quantity) {
|
||||
if (item.quantity == item.max_limit_quantity) {
|
||||
uni.showToast({
|
||||
title: '一次最多购买' + this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].max_limit_quantity + '件',
|
||||
title: '一次最多购买' + item.max_limit_quantity + '件',
|
||||
icon: 'none'
|
||||
});
|
||||
return
|
||||
}
|
||||
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity++;
|
||||
item.quantity++;
|
||||
this.carNum++;
|
||||
}
|
||||
const params = {
|
||||
goods_id_and_count: [
|
||||
{
|
||||
goods_id: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].id,
|
||||
count: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity,
|
||||
goods_id: item.goods_id,
|
||||
count: item.quantity,
|
||||
},
|
||||
],
|
||||
group_buy_id: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].group_buy_activity_info.id
|
||||
adver_id: item.adver_id
|
||||
}
|
||||
this.updateCar(params);
|
||||
},
|
||||
// 减少货品数量
|
||||
decreaseQuantity(goodsIndex, skuIndex) {
|
||||
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity > 0) {
|
||||
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity == this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].min_order_quantity) {
|
||||
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity = 0
|
||||
// 减少商品数量
|
||||
decreaseQuantity(index) {
|
||||
const item = this.goodsList[index]
|
||||
if (item.quantity > 0) {
|
||||
if (item.quantity == (item.min_order_quantity || 1)) {
|
||||
item.quantity = 0
|
||||
this.carNum = 0
|
||||
} else {
|
||||
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity--;
|
||||
item.quantity--;
|
||||
this.carNum--;
|
||||
}
|
||||
|
||||
const params = {
|
||||
goods_id_and_count: [
|
||||
{
|
||||
goods_id: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].id,
|
||||
count: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity,
|
||||
goods_id: item.goods_id,
|
||||
count: item.quantity,
|
||||
},
|
||||
],
|
||||
group_buy_id: this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].group_buy_activity_info.id
|
||||
adver_id: item.adver_id
|
||||
}
|
||||
this.updateCar(params);
|
||||
} else {
|
||||
@ -298,9 +220,9 @@ export default {
|
||||
// 跳转到购物车
|
||||
shopCar() {
|
||||
const item = {
|
||||
is_group_buy: 1,
|
||||
is_adver: 1,
|
||||
}
|
||||
NavgateTo("../shopCar/index?item=" + JSON.stringify(item));
|
||||
NavgateTo("/packages/shop/shopCar/index?item=" + JSON.stringify(item));
|
||||
},
|
||||
// 计算距离结束日期的剩余时间
|
||||
getEndTheCountdown(endTime) {
|
||||
|
||||
@ -6,14 +6,15 @@
|
||||
<view v-if="isLoading" class="loading">加载中...</view>
|
||||
<view v-else-if="recordsList.length === 0" class="empty-records">暂无聊天记录</view>
|
||||
<view v-else>
|
||||
<view v-for="record in recordsList" :key="record.mchId" class="record-item" @tap="goToChatPage(record)">
|
||||
<view v-for="record in recordsList" :key="record.id">
|
||||
<view class="record-item" @tap="goToChatPage(record)">
|
||||
<image class="record-avatar" :src="record.avatar || '/static/logo.png'" mode="aspectFill"></image>
|
||||
<view class="record-info">
|
||||
<view class="record-title-row">
|
||||
<text class="record-title">{{ record.title }}</text>
|
||||
<text class="record-time">{{ formatTime(record.lastMsgTime) }}</text>
|
||||
<text class="record-title">{{ record.contact_name }}</text>
|
||||
<text class="record-time">{{ record.update_time }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="record-last-msg">{{ record.lastMsg || '暂无消息' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -61,63 +62,14 @@ export default {
|
||||
page_num: this.page_num,
|
||||
page_size: this.page_size,
|
||||
}).then((res) => {
|
||||
console.log("🚀 ~ loadChattingRecords ~ res:", res)
|
||||
this.recordsList = res.msg_list
|
||||
})
|
||||
|
||||
// const response = await this.$http.get(apiArr.csGetMsgList);
|
||||
|
||||
// if (response.success && response.data && response.data.list) {
|
||||
// this.recordsList = response.data.list.map(item => ({
|
||||
// mchId: item.mchId,
|
||||
// title: item.title || `客服${item.mchId}`,
|
||||
// avatar: item.avatar,
|
||||
// lastMsg: item.lastMsg,
|
||||
// lastMsgTime: item.lastMsgTime || Date.now(),
|
||||
// unreadCount: item.unreadCount || 0
|
||||
// }));
|
||||
// } else {
|
||||
// // 使用模拟数据
|
||||
// this.recordsList = this.getMockRecords();
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error('加载聊天记录失败', error);
|
||||
// 使用模拟数据
|
||||
this.recordsList = this.getMockRecords();
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 获取模拟数据
|
||||
getMockRecords() {
|
||||
return [
|
||||
{
|
||||
mchId: '1001',
|
||||
title: '客服小明',
|
||||
avatar: '/static/logo.png',
|
||||
lastMsg: '您好,请问有什么可以帮助您的吗?',
|
||||
lastMsgTime: Date.now() - 30 * 60 * 1000,
|
||||
unreadCount: 0
|
||||
},
|
||||
{
|
||||
mchId: '1002',
|
||||
title: '客服小丽',
|
||||
avatar: '/static/logo.png',
|
||||
lastMsg: '您的问题我已经记录,稍后会有专人与您联系。',
|
||||
lastMsgTime: Date.now() - 2 * 60 * 60 * 1000,
|
||||
unreadCount: 1
|
||||
},
|
||||
{
|
||||
mchId: '1003',
|
||||
title: '客服小张',
|
||||
avatar: '/static/logo.png',
|
||||
lastMsg: '感谢您的咨询,还有其他问题吗?',
|
||||
lastMsgTime: Date.now() - 5 * 60 * 60 * 1000,
|
||||
unreadCount: 0
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(time) {
|
||||
const date = new Date(time);
|
||||
@ -152,13 +104,29 @@ export default {
|
||||
|
||||
// 跳转到聊天页面
|
||||
goToChatPage(record) {
|
||||
// 存储当前聊天对象的信息,供聊天页面使用
|
||||
uni.setStorageSync('currentChatTarget', record);
|
||||
const params = {
|
||||
mch_id: record.mch_id,
|
||||
}
|
||||
|
||||
request(apiArr.csGetMchContactList, "POST", params).then((res) => {
|
||||
if (res.rows && res.rows.length > 0) {
|
||||
res.rows.map(item => {
|
||||
item.employee_image = picUrl + item.employee_image;
|
||||
})
|
||||
const itemObj = res.rows.find(item => item.employee_mobile === record.two.account)
|
||||
|
||||
// 跳转到聊天页面
|
||||
uni.navigateTo({
|
||||
url: '/packages/customerService/index/index?mchId=' + record.mchId
|
||||
url: '/packages/customerService/index/index?item=' + JSON.stringify(itemObj)
|
||||
});
|
||||
} else {
|
||||
console.log("没有获取到客服列表数据");
|
||||
uni.showToast({
|
||||
title: '该客服不存在',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
/* 客服聊天页面样式 */
|
||||
page {
|
||||
background-color: #f6f7fb;
|
||||
overflow-y: hidden;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 聊天容器 */
|
||||
@ -10,6 +11,11 @@ page {
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f6f7fb;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 聊天头部 */
|
||||
@ -22,6 +28,8 @@ page {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding-bottom: 15rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
@ -130,6 +138,8 @@ page {
|
||||
padding: 10px 15px;
|
||||
border-top: 1px solid #eee;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<template>
|
||||
packages/customerService/index/index<template>
|
||||
<view class="chat-container">
|
||||
<!-- 聊天头部 -->
|
||||
<view :style="{ paddingTop: top + 'px', height: localHeight + 'px' }" class="chat-header">
|
||||
@ -15,8 +15,8 @@
|
||||
<view v-if="connectingStatus" class="connecting-status">{{ connectingStatus }}</view>
|
||||
|
||||
<!-- 聊天消息区域 -->
|
||||
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true"
|
||||
@scrolltoupper="loadMoreHistory">
|
||||
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true" @scrolltoupper="loadMoreHistory"
|
||||
@scrolltolower="loadMoreHistory" lower-threshold="100" upper-threshold="100">
|
||||
<!-- 加载历史消息提示 -->
|
||||
<view v-if="isLoadingHistory" class="message-time">加载历史消息...</view>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
'other': !message.isSelf,
|
||||
'loading': message.isLoading
|
||||
}" class="message-item">
|
||||
<image :src="message.isSelf ? userAvatar : (chatTarget.avatar || '/static/logo.png')" class="message-avatar"
|
||||
<image :src="message.isSelf ? userAvatar : (chatTarget.employee_image)" class="message-avatar"
|
||||
mode="aspectFill"></image>
|
||||
<view class="message-content">
|
||||
{{ message.content }}
|
||||
@ -44,7 +44,9 @@
|
||||
<view class="chat-input-area">
|
||||
<view class="input-container">
|
||||
<textarea v-model="inputMessage" :adjust-position="true" class="message-input" placeholder="请输入消息..."
|
||||
@confirm="sendMessage" @input="handleInput"></textarea>
|
||||
@confirm="sendMessage" @input="handleInput" auto-height hold-keyboard="true"
|
||||
enable-keyboard-accessory-view="true" cursor-spacing="10" maxlength="500" @focus="onInputFocus"
|
||||
@blur="onInputBlur"></textarea>
|
||||
<button :disabled="!canSend || !client || !isConnected" class="send-btn" @tap="sendMessage">
|
||||
发送
|
||||
</button>
|
||||
@ -54,12 +56,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { menuButtonInfo, request } from '@/utils'
|
||||
import { picUrl, menuButtonInfo, request, NavgateTo } from "../../../utils";
|
||||
import { apiArr } from '@/api/customerService'
|
||||
import MqttUtils from '@/utils/mqtt'
|
||||
import mqttTool from '@/utils/mqtt'
|
||||
|
||||
export default {
|
||||
data(){
|
||||
data() {
|
||||
return {
|
||||
localHeight: '',
|
||||
top: '',
|
||||
@ -71,7 +73,7 @@ export default {
|
||||
openId: '' // 接收方的open_id
|
||||
},
|
||||
// 用户头像
|
||||
userAvatar: '/static/logo.png',
|
||||
userAvatar: '',
|
||||
// 消息列表
|
||||
messages: [],
|
||||
// 输入的消息
|
||||
@ -93,36 +95,69 @@ export default {
|
||||
client: null,
|
||||
mqttConfig: {},
|
||||
// 重连失败提示定时器
|
||||
reconnectFailedTimer: null
|
||||
reconnectFailedTimer: null,
|
||||
// 分页参数
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
// 是否还有更多历史消息
|
||||
hasMoreHistory: true,
|
||||
// 滚动到底部的标记
|
||||
scrollToBottomFlag: false
|
||||
}
|
||||
},
|
||||
onLoad(options){
|
||||
onLoad(options) {
|
||||
const meun = menuButtonInfo()
|
||||
this.top = meun.top
|
||||
this.localHeight = meun.height
|
||||
// 获取聊天对象信息
|
||||
if (options.item) {
|
||||
this.chatTarget = JSON.parse(options.item)
|
||||
this.chatTarget.title = `客服${ this.chatTarget.employee_name }`
|
||||
this.chatTarget.title = `客服${this.chatTarget.employee_name}`
|
||||
}
|
||||
// 初始化MQTT连接
|
||||
this.initChat()
|
||||
this.getMqttConfig()
|
||||
// 初始化用户头像
|
||||
this.userAvatar = picUrl + uni.getStorageSync('headPhoto')
|
||||
},
|
||||
onShow(){
|
||||
onShow() {
|
||||
},
|
||||
methods: {
|
||||
async connect(){
|
||||
async connect() {
|
||||
this.client = null
|
||||
const options = {
|
||||
clientId: this.selfClientId
|
||||
}
|
||||
this.client = MqttUtils.connect(options)
|
||||
|
||||
// 添加连接状态回调
|
||||
const callbacks = {
|
||||
onConnect: () => {
|
||||
console.log('客服连接成功')
|
||||
this.isConnected = true
|
||||
this.connectingStatus = ''
|
||||
},
|
||||
onDisconnect: this.onDisconnect.bind(this),
|
||||
onError: (error) => {
|
||||
console.error('客服连接错误:', error)
|
||||
this.isConnected = false
|
||||
this.connectingStatus = '连接错误,请重试'
|
||||
},
|
||||
onReconnect: () => {
|
||||
console.log('客服正在重连...')
|
||||
this.isConnected = false
|
||||
this.connectingStatus = '连接已断开,正在重连...'
|
||||
}
|
||||
}
|
||||
|
||||
this.client = mqttTool.connect(options, callbacks)
|
||||
this.isConnected = !!this.client
|
||||
|
||||
await this.subscribe()
|
||||
this.client.on('message', (topic, message) => {
|
||||
let de = new TextDecoder('utf-8')
|
||||
let msg = de.decode(message)
|
||||
let jsMsg = JSON.parse(msg)
|
||||
const msgStr = Buffer.from(message).toString('utf8'); // 二进制转UTF-8字符串
|
||||
const msg = JSON.parse(msgStr); // 后续解析逻辑不变
|
||||
|
||||
let jsMsg = msg // 直接使用已解析的对象,无需再次解析
|
||||
console.log('收到消息', topic, msg)
|
||||
if (jsMsg.send_client === this.selfClientId || jsMsg.receive_client === this.selfClientId) {
|
||||
console.log('接收或发送人是我')
|
||||
@ -140,11 +175,12 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
async subscribe(){
|
||||
async subscribe() {
|
||||
if (this.isConnected && this.client) {
|
||||
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, function(err){
|
||||
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, (err) => {
|
||||
if (!err) {
|
||||
console.log('订阅成功', 'contact/message/receive_msg', { qos: 0 })
|
||||
this.connectingStatus = ''
|
||||
} else {
|
||||
console.log('订阅失败:', err)
|
||||
this.connectingStatus = '订阅失败,请重试'
|
||||
@ -152,28 +188,32 @@ export default {
|
||||
})
|
||||
} else {
|
||||
console.log('连接失败', this.isConnected, this.client)
|
||||
this.connectingStatus = '连接失败,请重试'
|
||||
}
|
||||
},
|
||||
// 初始化聊天
|
||||
async initChat(){
|
||||
async initChat() {
|
||||
try {
|
||||
// 显示连接状态
|
||||
this.connectingStatus = '连接中...'
|
||||
this.connectingStatus = '正在连接客服...'
|
||||
await this.connect()
|
||||
// 连接成功后启动心跳包
|
||||
this.startKeepalive()
|
||||
// 连接成功后立即加载历史消息
|
||||
this.loadHistoryMessages()
|
||||
} catch (error) {
|
||||
console.error('初始化聊天失败', error)
|
||||
this.connectingStatus = '连接失败,请重试'
|
||||
this.connectingStatus = '连接失败,请检查网络'
|
||||
|
||||
// 失败后尝试重新连接
|
||||
setTimeout(() => {
|
||||
this.reconnectFailedTimer = setTimeout(() => {
|
||||
this.initChat()
|
||||
}, 3000)
|
||||
}
|
||||
},
|
||||
|
||||
// 获取MQTT连接配置
|
||||
async getMqttConfig(){
|
||||
console.log('🚀 ~ getMqttConfig ~ getMqttConfig:', 11111)
|
||||
async getMqttConfig() {
|
||||
try {
|
||||
// 如果没有已创建的实例或clientId,则通过API获取
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -204,19 +244,16 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// MQTT断开连接回调 (为了兼容旧的调用)
|
||||
onDisconnect(packet){
|
||||
// MQTT断开连接回调
|
||||
onDisconnect(packet) {
|
||||
console.log('MQTT连接断开', packet)
|
||||
this.isConnected = false
|
||||
this.client = null
|
||||
|
||||
// 根据断开原因设置不同的连接状态文本
|
||||
if (packet.error) {
|
||||
if (packet && packet.error) {
|
||||
// 连接失败的情况
|
||||
this.connectingStatus = '连接失败,请检查网络或服务器'
|
||||
} else
|
||||
if (packet.reconnecting) {
|
||||
// 正在重连的情况
|
||||
this.connectingStatus = '连接已断开,正在重连...'
|
||||
this.connectingStatus = '连接失败,请检查网络'
|
||||
} else {
|
||||
// 其他断开连接的情况
|
||||
this.connectingStatus = '连接已断开,正在重连...'
|
||||
@ -227,9 +264,54 @@ export default {
|
||||
},
|
||||
|
||||
// 加载历史消息
|
||||
async loadHistoryMessages(){
|
||||
async loadHistoryMessages() {
|
||||
if (!this.hasMoreHistory || this.isLoadingHistory) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
this.isLoadingHistory = true
|
||||
|
||||
// 确保已经获取了mqttConfig.bind_id
|
||||
if (!this.mqttConfig.bind_id) {
|
||||
await this.getMqttConfig()
|
||||
}
|
||||
|
||||
const params = {
|
||||
bind_id: this.mqttConfig.bind_id,
|
||||
order: 'desc', // 按时间降序排列
|
||||
page_num: this.pageNum,
|
||||
page_size: this.pageSize
|
||||
}
|
||||
|
||||
console.log('请求历史消息参数:', params)
|
||||
const res = await request(apiArr.csGetMsgRecord, 'POST', params)
|
||||
|
||||
console.log('历史消息返回结果:', res)
|
||||
if (res && res.code === 1 && res.data && res.data.msg_record) {
|
||||
const historyMessages = res.data.msg_record
|
||||
|
||||
// 如果没有更多历史消息了
|
||||
if (historyMessages.length === 0) {
|
||||
this.hasMoreHistory = false
|
||||
return
|
||||
}
|
||||
|
||||
// 将获取到的历史消息添加到消息列表开头
|
||||
// 这里需要根据消息的发送方判断是否是自己发送的消息
|
||||
const formattedMessages = historyMessages.map(msg => ({
|
||||
content: msg.content,
|
||||
time: new Date(msg.create_time).getTime(),
|
||||
isSelf: msg.send_client === this.mqttConfig.clientId,
|
||||
isLoading: false
|
||||
})).reverse() // 因为是按时间降序获取的,所以需要反转
|
||||
|
||||
// 添加到消息列表开头
|
||||
this.messages = [...formattedMessages, ...this.messages]
|
||||
|
||||
// 增加页码
|
||||
this.pageNum++
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载历史消息失败', error)
|
||||
} finally {
|
||||
@ -238,14 +320,14 @@ export default {
|
||||
},
|
||||
|
||||
// 加载更多历史消息
|
||||
loadMoreHistory(){
|
||||
if (this.isLoadingHistory) {
|
||||
loadMoreHistory() {
|
||||
if (!this.isLoadingHistory && this.hasMoreHistory) {
|
||||
this.loadHistoryMessages()
|
||||
}
|
||||
// 这里可以实现加载更多历史消息的逻辑
|
||||
},
|
||||
|
||||
// 发送消息
|
||||
sendMessage(){
|
||||
sendMessage() {
|
||||
const content = this.inputMessage.trim()
|
||||
console.log('发送消息', content)
|
||||
if (!content || !this.client || !this.isConnected) return
|
||||
@ -281,12 +363,27 @@ export default {
|
||||
},
|
||||
|
||||
// 处理输入事件
|
||||
handleInput(){
|
||||
handleInput() {
|
||||
this.canSend = this.inputMessage.trim().length > 0
|
||||
},
|
||||
|
||||
onInputFocus() {
|
||||
// 输入框获取焦点时,设置滚动到底部的标记
|
||||
this.scrollToBottomFlag = true;
|
||||
setTimeout(() => {
|
||||
if (this.scrollToBottomFlag) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}, 300);
|
||||
},
|
||||
|
||||
onInputBlur() {
|
||||
// 输入框失去焦点时,重置滚动标记
|
||||
this.scrollToBottomFlag = false;
|
||||
},
|
||||
|
||||
// 是否需要显示时间分割线
|
||||
needShowTime(index){
|
||||
needShowTime(index) {
|
||||
if (index === 0) return true
|
||||
|
||||
const currentMsg = this.messages[index]
|
||||
@ -297,28 +394,28 @@ export default {
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(time){
|
||||
formatTime(time) {
|
||||
const date = new Date(time)
|
||||
const hours = date.getHours().toString().padStart(2, '0')
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||
|
||||
return `${ hours }:${ minutes }`
|
||||
return `${hours}:${minutes}`
|
||||
},
|
||||
|
||||
// 滚动到底部
|
||||
scrollToBottom(){
|
||||
scrollToBottom() {
|
||||
setTimeout(() => {
|
||||
this.scrollToView = 'msg-' + (this.messages.length - 1)
|
||||
}, 100)
|
||||
},
|
||||
|
||||
// 返回上一页
|
||||
goBack(){
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
// 启动心跳包 - 增强版:添加错误处理和状态检查
|
||||
startKeepalive(){
|
||||
startKeepalive() {
|
||||
// 停止之前的定时器
|
||||
this.stopKeepalive()
|
||||
|
||||
@ -353,7 +450,7 @@ export default {
|
||||
},
|
||||
|
||||
// 停止心跳包
|
||||
stopKeepalive(){
|
||||
stopKeepalive() {
|
||||
if (this.keepaliveTimer) {
|
||||
clearInterval(this.keepaliveTimer)
|
||||
this.keepaliveTimer = null
|
||||
@ -361,7 +458,7 @@ export default {
|
||||
},
|
||||
|
||||
// 跳转到切换客服页面
|
||||
goToChangeService(){
|
||||
goToChangeService() {
|
||||
uni.navigateTo({
|
||||
url: '/packages/customerService/changeService/index?currentMchId=' + this.chatTarget.mchId
|
||||
})
|
||||
@ -369,7 +466,7 @@ export default {
|
||||
},
|
||||
|
||||
// 页面卸载时停止心跳包
|
||||
onUnload(){
|
||||
onUnload() {
|
||||
// 断开MQTT连接
|
||||
if (this.client) {
|
||||
this.client.disconnect()
|
||||
|
||||
@ -116,8 +116,8 @@ export default {
|
||||
currentIndex: 0,
|
||||
checkedItems: [false, false, false, false],
|
||||
address: "",
|
||||
page_size: "10",
|
||||
page_num: "1",
|
||||
page_size: 10,
|
||||
page_num: 1,
|
||||
flag: false,
|
||||
merchatList: [],
|
||||
|
||||
@ -213,7 +213,7 @@ export default {
|
||||
});
|
||||
|
||||
if (res.rows.length == this.page_size) {
|
||||
this.page_num = this.page_num + 1;
|
||||
this.page_num = this.page_size + 10;
|
||||
this.flag = true;
|
||||
} else {
|
||||
this.flag = false;
|
||||
|
||||
@ -83,6 +83,7 @@ page {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 3rpx -3rpx 15rpx 0rpx rgba(255,27,27,0.05);
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
|
||||
@ -144,10 +144,11 @@ export default {
|
||||
},
|
||||
onLoad(options) {
|
||||
const params = {
|
||||
id: uni.getStorageSync("merchantInfo").id
|
||||
id: Number(uni.getStorageSync("merchantInfo").id)
|
||||
}
|
||||
request(apiArr.getMerchantInfo, "POST", params).then(res => {
|
||||
this.info = res
|
||||
uni.setStorageSync('merchantInfo', res)
|
||||
|
||||
// 确保onLoad执行完后再执行这两个方法
|
||||
this.page_num = 1
|
||||
|
||||
@ -121,8 +121,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
Money(newVal) {
|
||||
this.homeMoney = Math.round(newVal * (this.info.refund_property_fee_ratio || 0));
|
||||
this.integral = Math.round(newVal * (this.info.refund_user_points_ratio || 0));
|
||||
this.homeMoney = newVal * (this.info.refund_property_fee_ratio || 0);
|
||||
this.integral = newVal * (this.info.refund_user_points_ratio || 0);
|
||||
},
|
||||
|
||||
},
|
||||
@ -304,6 +304,7 @@ export default {
|
||||
success: (payRes) => {
|
||||
const params = {
|
||||
id: this.OrderMsg.id,
|
||||
back_wygjj: this.homeMoney,
|
||||
}
|
||||
request(apiArr.tradeQuery, "POST", params).then(res => {
|
||||
})
|
||||
|
||||
@ -375,9 +375,10 @@ page {
|
||||
|
||||
.shadowBox_img {
|
||||
width: 600rpx;
|
||||
height: 500rpx;
|
||||
height: 800rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.boxshadow_tit {
|
||||
@ -403,9 +404,88 @@ page {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wealBoxTit {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
margin-top: 30rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.wealBoxTit1 {
|
||||
color: #fe1535;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wealBoxTit2 {
|
||||
color: #fe1535;
|
||||
font-size: 26rpx;
|
||||
margin-left: 15rpx;
|
||||
}
|
||||
|
||||
.wealBox{
|
||||
width: 93%;
|
||||
height: 170rpx;
|
||||
margin: 15rpx auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wealBoxItem{
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
margin: 0 10rpx;
|
||||
border-radius: 15rpx;
|
||||
padding: 20rpx 10rpx;
|
||||
text-align: center;
|
||||
display: flex; /* 添加 flex 布局 */
|
||||
flex-direction: column; /* 设置主轴为垂直方向 */
|
||||
justify-content: space-between; /* 垂直方向上平均分布 */
|
||||
align-items: center; /* 水平方向居中 */
|
||||
}
|
||||
|
||||
|
||||
.wealBoxItem1{
|
||||
background-color: #fff4f1;
|
||||
}
|
||||
|
||||
.wealBoxItem2{
|
||||
background-color: #fff7f1;
|
||||
}
|
||||
|
||||
.wealBoxItem3{
|
||||
background-color: #fffaf0;
|
||||
}
|
||||
|
||||
.wealBoxItemTop{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wealBoxItemTop image{
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.wealBoxItemBottom{
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 30rpx;
|
||||
}
|
||||
|
||||
.boxbottom1 {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.boxbottom {
|
||||
width: 100%;
|
||||
margin-top: 50rpx;
|
||||
margin-bottom: 50rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@ -428,25 +508,25 @@ page {
|
||||
.shadowBox1 {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.shadowBox1Item_btn{
|
||||
.shadowBox1Item_btn {
|
||||
width: 110rpx;
|
||||
height: 150rpx;
|
||||
border: 1rpx solid red;
|
||||
position: absolute;
|
||||
left: 100rpx;
|
||||
opacity:0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.shadowBox2Item_btn{
|
||||
.shadowBox2Item_btn {
|
||||
width: 110rpx;
|
||||
height: 150rpx;
|
||||
border: 1rpx solid red;
|
||||
position: absolute;
|
||||
right: 100rpx;
|
||||
opacity:0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.shadowBox1Item {
|
||||
@ -508,7 +588,7 @@ page {
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.empty-tip{
|
||||
.empty-tip {
|
||||
height: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
|
||||
@ -233,11 +233,59 @@
|
||||
已支付成功
|
||||
</view>
|
||||
<view class="boxshadow_img">
|
||||
<view>核销码:{{ verifyCode }}</view>
|
||||
<view v-if="verifyCode">核销码:{{ verifyCode }}</view>
|
||||
<!-- <image
|
||||
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_share_img.png">
|
||||
</image> -->
|
||||
</view>
|
||||
<view>
|
||||
<view class="wealBoxTit">
|
||||
<view class="wealBoxTit1">下单福利</view>
|
||||
<view class="wealBoxTit2">已获得</view>
|
||||
</view>
|
||||
<view class="wealBox">
|
||||
<view class="wealBoxItem wealBoxItem1">
|
||||
<view class="wealBoxItemTop">
|
||||
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/activity_fen.png" mode="aspectFit">
|
||||
</image>
|
||||
<view>石榴分</view>
|
||||
</view>
|
||||
<view>
|
||||
{{ slFen }}
|
||||
</view>
|
||||
<view class="wealBoxItemBottom">
|
||||
可抵扣 ¥{{ slFen }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="wealBoxItem wealBoxItem2">
|
||||
<view class="wealBoxItemTop">
|
||||
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/activity_zi.png" mode="aspectFit">
|
||||
</image>
|
||||
<view>石榴籽</view>
|
||||
</view>
|
||||
<view>
|
||||
{{ slZi }}
|
||||
</view>
|
||||
<view class="wealBoxItemBottom">
|
||||
可抵扣 ¥{{ slZi }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="wealBoxItem wealBoxItem3">
|
||||
<view class="wealBoxItemTop">
|
||||
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/activity_jin.png" mode="aspectFit"/>
|
||||
<view>石榴金</view>
|
||||
</view>
|
||||
<view>
|
||||
{{ slJin }}
|
||||
</view>
|
||||
<view class="wealBoxItemBottom">
|
||||
可抵扣 ¥{{ slJin }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom">
|
||||
<view class="boxbottom1">
|
||||
<view class="boxbottom">
|
||||
<view class="line1"></view>
|
||||
赶快邀请好友来下单吧
|
||||
@ -270,6 +318,8 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 海报 -->
|
||||
<view class="shadow" @click="changeShadow2" v-if="boxshadow2">
|
||||
@ -315,6 +365,10 @@ export default {
|
||||
orderList2: [],
|
||||
carList: [],
|
||||
|
||||
slJin: 0,
|
||||
slFen: 0,
|
||||
slZi: 0,
|
||||
|
||||
// 团购活动id
|
||||
group_buy_activity_id: 0,
|
||||
|
||||
@ -338,7 +392,6 @@ export default {
|
||||
},
|
||||
onLoad(options) {
|
||||
this.carList = JSON.parse(options.shopCarList)
|
||||
console.log("🚀 ~ onLoad ~ JSON.parse(options.shopCarList):", JSON.parse(options.shopCarList))
|
||||
},
|
||||
onShow() {
|
||||
this.getUserAddress()
|
||||
@ -425,7 +478,6 @@ export default {
|
||||
}
|
||||
},
|
||||
increaseQuantity(item) {
|
||||
console.log("🚀 ~ increaseQuantity ~ item:", item)
|
||||
const currentTime = new Date().getTime();
|
||||
const startTime = new Date(item.commodity_goods_info.group_buy_activity_info?.start_time).getTime();
|
||||
const endTime = new Date(item.commodity_goods_info.group_buy_activity_info?.end_time).getTime();
|
||||
@ -600,7 +652,8 @@ export default {
|
||||
// 原始逻辑:创建订单后再进行支付
|
||||
const params = {
|
||||
user_id: uni.getStorageSync('userId'),
|
||||
is_group_buy: isGroupBuyValid,
|
||||
// 先判断shopCarList数据中是否包含isAdver且为true
|
||||
order_cate : this.carList.some(item => item.isAdver === true) ? 3 : (isGroupBuyValid ? 2 : 1),
|
||||
goods_list: Object.keys(this.supplierGroups).map(supplierId => {
|
||||
const group = this.supplierGroups[supplierId];
|
||||
const firstItem = group[0];
|
||||
@ -662,11 +715,13 @@ export default {
|
||||
success: (payRes) => {
|
||||
const params = {
|
||||
order_id: orderId,
|
||||
from: 2,
|
||||
from: this.carList.some(item => item.isAdver === true) ? 3 : (isGroupBuyValid ? 2 : 1),
|
||||
group_buy_activity_id: this.group_buy_activity_id,
|
||||
adver_id: this.carList.some(item => item.isAdver === true) ? this.carList.find(item => item.isAdver === true).adver_id : ''
|
||||
}
|
||||
request(apiArr.queryOrder, "POST", params).then(res => {
|
||||
this.verifyCode = res.verification_code
|
||||
this.slJin = res.shiliu_money
|
||||
this.boxshadow1 = true
|
||||
})
|
||||
},
|
||||
|
||||
@ -228,7 +228,8 @@ export default {
|
||||
isDayshow: false,
|
||||
isParcelPostchecked: false,
|
||||
parcelPostshow: false,
|
||||
is_group_buy: ''
|
||||
is_group_buy: '',
|
||||
is_adver: ''
|
||||
};
|
||||
},
|
||||
// watch: {
|
||||
@ -297,14 +298,20 @@ export default {
|
||||
this.$u.toast("请选择商品");
|
||||
return;
|
||||
}
|
||||
// 给每个商品添加isAdver=true参数
|
||||
const updatedArr = arr.map(item => ({
|
||||
...item,
|
||||
isAdver: item.adver_id ? true : ''
|
||||
}));
|
||||
// NavgateTo(`../submitOrder/index?shopCarList=${JSON.stringify(arr)}`);
|
||||
NavgateTo(`../groupPurchaseSubmit/index?shopCarList=${JSON.stringify(arr)}`);
|
||||
NavgateTo(`../groupPurchaseSubmit/index?shopCarList=${JSON.stringify(updatedArr)}`);
|
||||
},
|
||||
|
||||
// 获取购物车列表
|
||||
getShopCar() {
|
||||
const params = {
|
||||
is_group_buy: this.is_group_buy
|
||||
is_group_buy: this.is_group_buy,
|
||||
is_adver: this.is_adver
|
||||
}
|
||||
request(apiArr.getCar, "POST", params).then((res) => {
|
||||
if (res.normal_cart_list.length > 0) {
|
||||
@ -728,6 +735,7 @@ export default {
|
||||
this.top = meun.top;
|
||||
this.localHeight = meun.height;
|
||||
this.is_group_buy = options.item ? JSON.parse(options.item).is_group_buy : ''
|
||||
this.is_adver = options.item ? JSON.parse(options.item).is_adver : ''
|
||||
this.getShopCar();
|
||||
},
|
||||
onShow() {
|
||||
|
||||
@ -109,6 +109,7 @@
|
||||
icon: 'success',
|
||||
mask: true
|
||||
})
|
||||
uni.setStorageSync('headPhoto', this.avatarInfo.picUrl)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}, 2000)
|
||||
|
||||
@ -93,11 +93,12 @@
|
||||
|
||||
<!-- 广告横幅 -->
|
||||
<view class="serverList1">
|
||||
<view class="serverList1_left" @click="toAdvertisingView">
|
||||
<view class="serverList1_left" @click="toAdvertisingView(serverLeftList)">
|
||||
<image :src="serverLeft" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="serverList1_right">
|
||||
<view :class="['serverItemRight', `serverItemRight${index + 1}`]" @tap="headerServerClick(item)"
|
||||
<view :class="['serverItemRight', `serverItemRight${index + 1}`]"
|
||||
@tap="index === 1 ? toAdvertisingView(serverRightList) : headerServerClick(item)"
|
||||
v-for="(item, index) in serverRightList" :key="index">
|
||||
<image :src="item.pic_src" mode="" />
|
||||
</view>
|
||||
@ -308,6 +309,7 @@ export default {
|
||||
|
||||
// 中部1左侧广告
|
||||
serverLeft: '',
|
||||
serverLeftList: [],
|
||||
|
||||
// 中部1右侧广告
|
||||
serverRightList: [],
|
||||
@ -351,8 +353,9 @@ export default {
|
||||
},
|
||||
|
||||
// 广告商品跳转
|
||||
toAdvertisingView(item) {
|
||||
NavgateTo('/packages/advertising/index/index')
|
||||
toAdvertisingView(itemArry) {
|
||||
const item = itemArry[0]
|
||||
NavgateTo('/packages/advertising/index/index?id=' + item.id)
|
||||
},
|
||||
|
||||
async goToWuye() {
|
||||
@ -679,6 +682,7 @@ export default {
|
||||
}, { silent: false });
|
||||
|
||||
if (res.rows.length) {
|
||||
this.serverLeftList = res.rows
|
||||
let filterRes = this.filterShowList(res?.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
|
||||
@ -90,6 +90,7 @@ export default {
|
||||
uni.setStorageSync('userId', res2.user_id);
|
||||
uni.setStorageSync('openId', res2.open_id);
|
||||
uni.setStorageSync('shopId', res2.wshop_id);
|
||||
uni.setStorageSync('headPhoto', res2.img);
|
||||
|
||||
this.isLogin = true;
|
||||
that.getUserInfo();
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
<view>繁华币</view>
|
||||
</view>
|
||||
<view class="section_label">
|
||||
<view>0.00元</view>
|
||||
<view>{{ userInfo.property_housing_fund }}元</view>
|
||||
<view>物业费公积金</view>
|
||||
</view>
|
||||
<view class="section_label">
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import mqtt from 'mqtt/dist/mqtt'
|
||||
import Vue from 'vue'
|
||||
// 引入Buffer,适配小程序环境
|
||||
import { Buffer } from 'buffer';
|
||||
// 挂载到全局,确保所有文件可访问
|
||||
if (typeof window !== 'undefined') {
|
||||
window.Buffer = Buffer;
|
||||
} else if (typeof global !== 'undefined') {
|
||||
global.Buffer = Buffer;
|
||||
}
|
||||
|
||||
let mqttTool = {
|
||||
client: null
|
||||
}
|
||||
|
||||
mqttTool.connect = function(params){
|
||||
mqttTool.connect = function(params, callbacks = {}){
|
||||
let options = {
|
||||
clientId: params.clientId,
|
||||
username: 'dev01',
|
||||
@ -20,11 +28,36 @@ mqttTool.connect = function(params){
|
||||
client = mqtt.connect('wx://api.hshuishang.com:8084/mqtt', options)
|
||||
console.log('WX', client)
|
||||
mqttTool.client = client
|
||||
if (mqttTool.client) {
|
||||
console.log('连接成功')
|
||||
} else {
|
||||
console.log('连接失败')
|
||||
|
||||
// 设置连接状态回调
|
||||
if (callbacks.onConnect) {
|
||||
client.on('connect', callbacks.onConnect)
|
||||
}
|
||||
|
||||
if (callbacks.onDisconnect) {
|
||||
client.on('disconnect', callbacks.onDisconnect)
|
||||
}
|
||||
|
||||
if (callbacks.onError) {
|
||||
client.on('error', callbacks.onError)
|
||||
}
|
||||
|
||||
if (callbacks.onReconnect) {
|
||||
client.on('reconnect', callbacks.onReconnect)
|
||||
}
|
||||
|
||||
client.on('connect', function() {
|
||||
console.log('MQTT连接成功')
|
||||
})
|
||||
|
||||
client.on('error', function(error) {
|
||||
console.log('MQTT连接错误:', error)
|
||||
})
|
||||
|
||||
client.on('reconnect', function() {
|
||||
console.log('MQTT正在重连...')
|
||||
})
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@ -164,6 +164,14 @@ buffer@^5.5.0:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
buffer@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
callback-stream@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz"
|
||||
@ -384,7 +392,7 @@ help-me@^1.0.1:
|
||||
through2 "^2.0.1"
|
||||
xtend "^4.0.0"
|
||||
|
||||
ieee754@^1.1.13:
|
||||
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user