diff --git a/api/gift.js b/api/gift.js index 3f33c62..17e7767 100644 --- a/api/gift.js +++ b/api/gift.js @@ -124,3 +124,27 @@ export function computedSojoumGroupBuyGiftOrderPrice(params) { login: true }) } + +/** + * 文生图发起生成 + * @param {*} data + * @returns + */ + +export function aiGiftImageGenerate(data) { + return request.post("/aiGiftImage/generate", data, { + login: true + }) +} + +/** + * 文生图状态查询 + * @param {*} params + * @returns + */ + +export function aiGiftImageStatus(params) { + return request.get("/aiGiftImage/" + params.productId, { + login: true + }) +} diff --git a/api/user.js b/api/user.js index bc264e6..e437fb9 100644 --- a/api/user.js +++ b/api/user.js @@ -603,3 +603,11 @@ export function queryUserGuide(params) { export function setUserGuide(params) { return request.post('/user/guide/status', params) } + +/** + * 提现规则 + */ +export function getWithdrawalRules() { + return request.get('/extract/rule') +} + diff --git a/components/ProductWindow.vue b/components/ProductWindow.vue index 1e6ea87..c9a1d09 100644 --- a/components/ProductWindow.vue +++ b/components/ProductWindow.vue @@ -35,8 +35,7 @@ v-for="(subItem, subIndex) in item.attrValue" :key="subIndex" :class="{ - 'actived': subItem.check, - 'disabled': !subItem.canUsed + 'actived': subItem.check }" class="itemn v12-radius-40" @click="tapAttr(index, subIndex, subItem)" @@ -218,9 +217,9 @@ export default { }, tapAttr(index, subIndex, subItem) { // 缺货的点击了没效果 - if (!subItem.canUsed || subItem.check) { - return - } + // if (!subItem.canUsed || subItem.check) { + // return + // } this.attrObj.productAttr[index].attrValue.map((subItem, subIdx) => { subItem.check= false if (subIndex === subIdx) { diff --git a/pages/VideoPlayBackList/VideoPlayBackList.vue b/pages/VideoPlayBackList/VideoPlayBackList.vue index e74a49a..3256fd7 100644 --- a/pages/VideoPlayBackList/VideoPlayBackList.vue +++ b/pages/VideoPlayBackList/VideoPlayBackList.vue @@ -41,7 +41,9 @@ - + 加载中... + + 暂无数据 @@ -73,12 +75,16 @@ export default { leftHeight: 0, rightHeight: 0, isWait: false, + requestId: 0, pageKeyId: Object.freeze('findVideoList') } }, computed: { hasList() { return this.leftList.length + this.rightList.length > 0 + }, + showEmpty() { + return !this.isWait && !this.hasList } }, onLoad(options) { @@ -106,7 +112,9 @@ export default { changeType(item) { this.type = item.value this.page = 1 - this.resetList() + // 使进行中的请求失效并解锁,避免切换时被上一次请求阻塞 + this.requestId++ + this.isWait = false this.fetchList() }, resetList() { @@ -117,6 +125,7 @@ export default { }, async fetchList() { if (this.isWait) return + const requestId = ++this.requestId this.isWait = true const params = { type: this.type, @@ -125,13 +134,17 @@ export default { } try { const res = await getVideoList(params) + // 请求已被更新的请求(如切换分类)取代,丢弃本次结果 + if (requestId !== this.requestId) return if (res.status === 200) { const items = res.data for (let i = 0; i < items.length; i++) { items[i].hide = true } - // 并行获取所有封面高度 + // 并行获取所有封面高度,完成后一次性替换列表,避免闪现空列表 const heights = await Promise.all(items.map(item => this.getImageHeight(item.cover))) + if (requestId !== this.requestId) return + if (this.page === 1) this.resetList() items.forEach((item, i) => { this.pushToColumn(item, heights[i] + TEXT_HEIGHT) }) @@ -139,7 +152,9 @@ export default { } catch (e) { // 忽略请求或图片尺寸获取失败 } finally { - this.isWait = false + if (requestId === this.requestId) { + this.isWait = false + } } }, getImageHeight(src) { @@ -252,4 +267,11 @@ export default { } } } + +.loading-more { + padding: 24rpx 0; + text-align: center; + font-size: 24rpx; + color: #999; +} diff --git a/pages/cloud/haveFun.vue b/pages/cloud/haveFun.vue index c8afdc6..fa0def4 100644 --- a/pages/cloud/haveFun.vue +++ b/pages/cloud/haveFun.vue @@ -114,7 +114,8 @@ - + + 暂无数据 @@ -203,6 +204,7 @@ export default { isNext: false, townConfig: {}, townList: [], + townLoaded: false, randomSeed: null, hotelBanner: [], goodCityId: '', @@ -519,6 +521,8 @@ export default { } getAncientTownList(params).then(res => { this.townList = res.data.records + }).finally(() => { + this.townLoaded = true }) return } diff --git a/pages/shop/GoodsCon/index.vue b/pages/shop/GoodsCon/index.vue index afb8657..20df328 100644 --- a/pages/shop/GoodsCon/index.vue +++ b/pages/shop/GoodsCon/index.vue @@ -309,7 +309,7 @@ - + @@ -579,6 +579,7 @@ export default { mixins: [pageListenMixins], data: function () { return { + appProductHideMerchant: '0', isGift: false, giftBg: '', // 商品信息是否展开 @@ -1210,6 +1211,7 @@ export default { this.posterData.price = this.storeInfo.price this.posterData.code = this.storeInfo.codeBase this.systemStore = data.systemStore + this.appProductHideMerchant = data.appProductHideMerchant const good_list = data.goodList || [] const goodArray = [] const count = Math.ceil(good_list.length / 6) diff --git a/pagesOrder/order/OrderDetails/index.vue b/pagesOrder/order/OrderDetails/index.vue index c9ea777..f5f405c 100644 --- a/pagesOrder/order/OrderDetails/index.vue +++ b/pagesOrder/order/OrderDetails/index.vue @@ -317,7 +317,7 @@ - + 实付款 @@ -498,15 +498,17 @@ 共{{ orderInfo.totalNum }}件商品 - - 实付款 - - - ¥ - - - {{ force2Decimal(orderInfo.payPrice) }} - + 立即付款 diff --git a/pagesUser/user/promotion/UserCash/index.vue b/pagesUser/user/promotion/UserCash/index.vue index 870d4a4..a73184a 100644 --- a/pagesUser/user/promotion/UserCash/index.vue +++ b/pagesUser/user/promotion/UserCash/index.vue @@ -23,7 +23,7 @@ 提现 - + 当前可提现金额: {{ commissionCount }} @@ -45,7 +45,7 @@ 提现 - + 当前可提现金额: {{ commissionCount }} diff --git a/pkg_common/views/room.vue b/pkg_common/views/room.vue index b89bc0e..9854a38 100644 --- a/pkg_common/views/room.vue +++ b/pkg_common/views/room.vue @@ -108,8 +108,11 @@ export default { uploadToken: null, //上传token socketOpen: false, + socketConnecting: false, // 是否正在建连 socketTask: null, socketMsgQueue: [], + hasConnected: false, // 是否成功建过连接 + reconnectHistory: false, // 重连后用服务端历史整体替换本地列表,防止消息重复 roomId: null, //房间ID content: "", //消息内容 @@ -136,30 +139,22 @@ export default { }, onShow() { this.content = uni.getStorageSync(this.merName+this.uid+this.storeId) - this.connectSocketInit(); - this.list = [] + // 已连接/连接中不重复建连;清空 list 会导致图片操作(触发 onHide/onShow)后页面白屏 + if (!this.socketOpen && !this.socketConnecting) { + this.connectSocketInit(); + } }, onUnload() { - if (this.socketOpen) { - this.socketTask.close(); - } - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); - }); + this.closeSocket(); uni.setStorageSync(this.merName+this.uid+this.storeId, this.content) }, onHide() { - if (this.socketOpen) { - this.socketTask.close(); - } - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); - }); + this.closeSocket(); uni.setStorageSync(this.merName+this.uid+this.storeId, this.content) }, methods: { toGoods(item) { - const itemJson = JSON.parse(item.msg_content) + const itemJson = this.wsJson(item.msg_content) if(!itemJson.goodsId) { // 提示数据错误 // uni.showToast({ @@ -177,7 +172,12 @@ export default { }) }, wsJson(json) { - return JSON.parse(json) + // 兼容脏数据,避免渲染时报错导致白屏 + try { + return JSON.parse(json) || {} + } catch (e) { + return {} + } }, // 拼接图片完整地址:七牛上传后消息里只存 key,需要补上资源域名;http 统一转 https imgUrl(content) { @@ -255,33 +255,68 @@ export default { }); }, - // 进入这个页面的时候创建websocket连接【整个页面随时使用】 + // 进入页面时创建websocket连接【整个页面随时使用】 connectSocketInit() { + if (this.socketOpen || this.socketConnecting) return; + this.socketConnecting = true; + // 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】 - this.socketTask = uni.connectSocket({ + const task = uni.connectSocket({ url: this.$SOCKET_URL, success: () => { } }) + if (!task) { + this.socketConnecting = false; + return; + } + this.socketTask = task; - uni.onSocketOpen(res => { - console.log('WebSocket连接已打开!', res); + // 任务级回调:全局 uni.onSocket* 每次进页面都会重复注册,导致消息重复处理、连接串台 + const isCurrent = () => this.socketTask === task; + + task.onOpen(() => { + if (!isCurrent()) return; this.socketOpen = true; + this.socketConnecting = false; + // 断线重连后重新加入房间;本地已有历史时用服务端历史整体替换,避免重复 + this.reconnectHistory = this.hasConnected && this.list.length > 0; + this.hasConnected = true; this.createRoom(); + // 补发连接未就绪期间排队的消息(如发图片时连接被隐藏页关闭) + if (this.socketMsgQueue.length) { + const queue = this.socketMsgQueue.splice(0); + queue.forEach(msg => this.sendSocketMessage(msg)); + } }); - uni.onSocketError(err => { - console.log('WebSocket连接打开失败,请检查!', err); - }); - - uni.onSocketMessage(res => { - console.log('收到服务器内容:', res.data); + task.onMessage(res => { + if (!isCurrent()) return; this.handleMessage(res.data); }); - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); + task.onError(err => { + console.log('WebSocket连接打开失败,请检查!', err); + if (!isCurrent()) return; + this.socketOpen = false; + this.socketConnecting = false; }); + + task.onClose(() => { + if (!isCurrent()) return; + this.socketOpen = false; + this.socketConnecting = false; + }); + }, + + closeSocket() { + this.socketOpen = false; + this.socketConnecting = false; + if (this.socketTask) { + try { + this.socketTask.close({}); + } catch (e) {} + } }, userInput(event) { @@ -321,11 +356,14 @@ export default { }, sendSocketMessage(msg) { - if (this.socketOpen) { - uni.sendSocketMessage({ + if (this.socketOpen && this.socketTask) { + this.socketTask.send({ data: msg, - success(res) { - console.log("消息发送成功", res,msg); + fail: () => { + // 发送失败说明连接可能已断开,重新排队并尝试重连后补发 + this.socketMsgQueue.push(msg); + this.closeSocket(); + this.connectSocketInit(); } }); } else { @@ -334,7 +372,12 @@ export default { }, handleMessage(str) { - let data = JSON.parse(str); + let data; + try { + data = JSON.parse(str); + } catch (e) { + return; + } switch (data.type) { case "room_id": this.roomId = data.msg_content; @@ -344,13 +387,23 @@ export default { case "leave": break; case "msg": - this.list.push(data.msg_content); - this.scrollLast(); + if (data.msg_content) { + this.list.push(data.msg_content); + this.scrollLast(); + } break; - case "msg_history": - this.list = data.msg_content.concat(this.list); + case "msg_history": { + const history = data.msg_content || []; + if (this.reconnectHistory) { + // 重连后服务端重发历史:整体替换,避免消息重复 + this.reconnectHistory = false; + this.list = history; + } else { + this.list = history.concat(this.list); + } this.scrollLast(); break; + } default: break; } diff --git a/pkg_join/views/shop.vue b/pkg_join/views/shop.vue index 495584a..45e8e44 100644 --- a/pkg_join/views/shop.vue +++ b/pkg_join/views/shop.vue @@ -6,7 +6,7 @@ labelWidth="216rpx" > - + 暂无店铺 - + @@ -670,9 +674,13 @@ {{ tab.name }} - + - + 暂无数据 - + diff --git a/pkg_product/views/submitOrder.vue b/pkg_product/views/submitOrder.vue index 73aca6a..a4bc5e5 100644 --- a/pkg_product/views/submitOrder.vue +++ b/pkg_product/views/submitOrder.vue @@ -333,7 +333,8 @@ export default { this.$yrouter.replace({ path: "/pages/order/MyOrder/index", query: { - type: 1 + type: 1, + tabIndex: 1 } }); break; @@ -355,7 +356,8 @@ export default { this.$yrouter.replace({ path: "/pages/order/MyOrder/index", query: { - type: 1 + type: 1, + tabIndex: 1 } }) break; @@ -365,7 +367,8 @@ export default { this.$yrouter.replace({ path: "/pages/order/MyOrder/index", query: { - type: 1 + type: 1, + tabIndex: 1 } }) }) @@ -376,7 +379,8 @@ export default { this.$yrouter.replace({ path: "/pages/order/MyOrder/index", query: { - type: 1 + type: 1, + tabIndex: 1 } }); }) diff --git a/pkg_user/views/gift/components/AiCoverPicker.vue b/pkg_user/views/gift/components/AiCoverPicker.vue new file mode 100644 index 0000000..2782b1f --- /dev/null +++ b/pkg_user/views/gift/components/AiCoverPicker.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/pkg_user/views/gift/components/GiftCard.vue b/pkg_user/views/gift/components/GiftCard.vue index 0d6cef1..c2a1717 100644 --- a/pkg_user/views/gift/components/GiftCard.vue +++ b/pkg_user/views/gift/components/GiftCard.vue @@ -1,25 +1,42 @@