import { getProductDataApi } from "@/api/item"; import { mapGetters, mapActions } from "vuex"; import { copyObject } from "@/utils/util"; export default { data() { return { options:'', pageType: "bill", //选择商品页面类别 用于区分不同功能的数据 suitInfo: [], //成品-商品信息 suitClassIndex: 0, //成品-当前商品类别下标 productInfo: [], //商品信息 pxClassInfo: [], //培训班开单列表 classIndex: 0, //当前商品类别下标 py: "", //拼音搜索条件 type: "", //库存预警时,固定为waring,其他情况不传或者传空 autoLoad: true, //自动获取商品信息 isLimit: true, //选择数量不能大于库存限制 //成品开单 suit_scroll_into_view:"", suit_top_list:'', suitTimeFun:"", suitFilterProductInfo:'', //组合开单 scroll_into_view:"", top_list:'', cached_top_list: null, scrollTimer: null, timeFun:"", filterProductInfo:'' }; }, onLoad(options) { this.options = options; const { pageType,shopId,id,name } = options; if (pageType) { this.pageType = pageType; } if(name){ uni.setNavigationBarTitle({ title: name }); } if (this.autoLoad) { this.initData(); if(this.isGhsProduct){ }else{ if(!this.$util.isEmpty(this.tabIndex)){ this.initData(); } } } }, computed: { ...mapGetters(["getSelectInfo", "getLimitBuyInfo"]), //当前页面选中的商品列表 selectList() { return this.getSelectInfo[this.pageType] || []; }, //当前页面限购信息列表 limitBuyList() { return this.getLimitBuyInfo[this.pageType] || []; }, scrollClassId() { const curClass = this.productInfo[this.classIndex]; if (curClass) { return `class_${curClass.classId}`; } return ""; }, //选择商品总价 allPrice() { let price = 0; if (this.selectList) { for (const item of this.selectList) { price += this.getSelectItemTotalPrice(item); } } return Math.round(price * 100) / 100; }, // 满减优惠总额 allReachDiscountAmount() { let discount = 0; if (this.selectList) { for (const item of this.selectList) { discount += this.getReachDiscountAmount(item); } } return Math.round(discount * 100) / 100; }, allPriceFun() { let price = 0; if (this.selectList) { // 唯一性处理,通过 id 去除重复商品 ---- 防止统计金额时因同一商品多次出现而重复计算 const newSelectList = this.selectList.filter( (item, index, self) => index === self.findIndex(t => t.id === item.id) ); for (const item of newSelectList) { price += this.getSelectItemTotalPrice(item); } } return Math.round(price * 100) / 100; }, //选择商品总数和总重要 allCount() { let bigLength = 0; let smallLength = 0; let weight = 0 if (this.selectList) { for (const item of this.selectList) { bigLength += item.bigCount smallLength += item.smallCount if(item.weight){ if(Number(item.bigCount)>0){ let bigAdd = Number(item.weight)*Number(item.bigCount) weight = Number(weight) + Number(bigAdd) }else{ let ratio = item.ratio||20 let unitWeight = item.weight/ratio let smallAdd = Number(unitWeight)*Number(item.smallCount) weight = Number(weight) + Number(smallAdd) } weight = weight.toFixed(2) weight = parseFloat(weight) } } } return {bigLength:bigLength,smallLength:smallLength,weight:weight}; }, allCountFun() { let bigLength = 0; let smallLength = 0; let weight = 0; if (this.selectList) { for (const item of this.selectList) { bigLength += item.bigCount; smallLength += item.smallCount; if (item.weight) { if (Number(item.bigCount) > 0) { let bigAdd = Number(item.weight) * Number(item.bigCount); weight = Number(weight) + Number(bigAdd); } else { let ratio = item.ratio || 20; let unitWeight = item.weight / ratio; let smallAdd = Number(unitWeight) * Number(item.smallCount); weight = Number(weight) + Number(smallAdd); } weight = weight.toFixed(2); weight = parseFloat(weight); } } } return { bigLength, smallLength, weight }; }, //描点-定位分类 suitScrollClassId() { const curClass = this.suitInfo[this.suitClassIndex]; if (curClass) { return `class_${curClass.classId}`; } return ""; }, //多风格-选择商品总价 allGoodsPrice() { let price = 0; if (this.selectList) { for (const item of this.selectList) { if(item.goodsStyle){ if(item.goodsStyle==0){ price += item.bigCount * Number(item.price); }else{ price += item.bigCount * Number(item.goodsStyleList[item.goodsStyleSelectIndex].price); } } } } return Math.round(price * 100) / 100; }, //多风格-选择商品总数 allGoodsCount() { let length = 0; this.selectList.forEach(element => { length += Number(element.bigCount) }) return length; }, //当前选中商品列表中是否有没有库存的商品 hasNoStock() { let has = false; if (this.selectList) { for (const item of this.selectList) { const { bigCount, smallCount, bigNum, bigUnit, smallNum, smallUnit, ratio } = item; const ratioNum = Number(ratio); if ( Number(bigCount) * ratioNum + Number(smallCount) > Number(bigNum) * ratioNum + Number(smallNum) ) { has = true; break; } } } return has; } }, onShow(){ // 购物车/分类等页面自行从 account 维度恢复,避免无 account 的 selectListcg 覆盖 if (this.autoLoad === false) { return; } if(this.pageType == 'cg' && !this.$util.isEmpty(this.option.id)){ }else{ if(uni.getStorageSync('selectList'+this.pageType)){ this.setSelectInfoByType({ type: this.pageType, info: uni.getStorageSync('selectList'+this.pageType) }) } } }, methods: { ...mapActions([ "setSelectInfoByType", "resetSelectInfoByType", "setLimitBuyInfoByType", "resetLimitBuyInfoByType" ]), isTrueValue(value) { return value === true || value === 1 || value === "1"; }, toSafeNumber(value) { const num = Number(value); return isNaN(num) ? 0 : num; }, /** 供货商--采购 / 预订:列表里同一花材可能在不同分类下 classId 不同,购物车应按 id 合并为一行 */ _shouldMergeSelectByProductId() { return this.pageType === "cg" || this.pageType === "bookCg"; }, /** property: 0=花束 goods,1=花材 item;历史花材数据无 property 时按花材处理 */ getItemProperty(item) { if (!item) return 1; if (item.property === 0 || item.property === '0') return 0; if (item.property === 1 || item.property === '1') return 1; return 1; }, isBouquetItem(item) { return this.getItemProperty(item) === 0; }, /** 购物车行唯一键:花束用 id+property+specGoodsId+activityType,花材用 id(+classId) */ getSelectRowKey(item) { if (!item || item.id === undefined || item.id === null) return ''; const property = this.getItemProperty(item); if (property === 0) { // 与 _selectRowMatches 对齐:同规格秒杀与普通购买必须分行,避免不同计价规则被合并 return `0_${item.id}_${item.specGoodsId || 0}_${item.activityType || ''}`; } if (this._shouldMergeSelectByProductId()) { return `1_${item.id}`; } return `1_${item.id}_${item.classId || 0}`; }, _mergeDuplicateSelectRows(list) { if (!Array.isArray(list) || list.length === 0) { return Array.isArray(list) ? [...list] : []; } const map = new Map(); const order = []; list.forEach(ele => { const key = this.getSelectRowKey(ele) || String(ele.id); if (!map.has(key)) { const copy = { ...ele }; copy.bigCount = Number(copy.bigCount) || 0; copy.smallCount = Number(copy.smallCount) || 0; if (copy.property === undefined || copy.property === null) { copy.property = this.getItemProperty(copy); } map.set(key, copy); order.push(key); } else { const prev = map.get(key); prev.bigCount = Number(prev.bigCount) + (Number(ele.bigCount) || 0); prev.smallCount = Number(prev.smallCount) + (Number(ele.smallCount) || 0); } }); return order.map(k => map.get(k)); }, _syncMergedSelectListIfNeeded() { if (!this._shouldMergeSelectByProductId()) return; const list = this.selectList; if (!list || !list.length) return; const merged = this._mergeDuplicateSelectRows(list); if (merged.length !== list.length) { this.setSelectInfoByType({ type: this.pageType, info: merged }); } }, _selectRowMatches(element, item) { if (!element || !item) return false; const eleProperty = this.getItemProperty(element); const itemProperty = this.getItemProperty(item); if (eleProperty !== itemProperty) return false; if (eleProperty === 0) { // 秒杀与普通购买同商品同规格也必须分行,避免不同计价规则的购物车行被合并 if ((element.activityType || '') !== (item.activityType || '')) return false; return String(element.id) === String(item.id) && String(element.specGoodsId || 0) === String(item.specGoodsId || 0); } if (this._shouldMergeSelectByProductId()) { return String(element.id) === String(item.id); } return element.id == item.id && element.classId == item.classId; }, getLimitBuyItemById(id) { if (!Array.isArray(this.limitBuyList)) { return null; } return this.limitBuyList.find(item => String(item.id) === String(id)) || null; }, isLimitSpecialItem(item) { const limitItem = this.getLimitBuyItemById(item.id); return !!(limitItem && this.isTrueValue(limitItem.isLimit) && this.isTrueValue(limitItem.specialPrice)); }, getItemReachPrice(item) { const reachPrice = Number(item.reachPrice); if (!isNaN(reachPrice) && reachPrice > 0) { return parseFloat(reachPrice); } const price = this.toSafeNumber(item.price || item.bigPrice); const reachNumDiscount = Number(item.reachNumDiscount) || 0; if (reachNumDiscount > 0 && price > reachNumDiscount) { const computed = parseFloat((price - reachNumDiscount).toFixed(2)); return computed <= 0 ? 0.01 : computed; } return 0; }, isReachDiscountReached(item) { const reachNum = Number(item.reachNum) || 0; if (reachNum <= 0) { return false; } const itemInfo = this.getSelectItemById(item.id, item.classId); return Number(itemInfo.bigCount) >= reachNum; }, getReachDiscountAmount(item) { if (!this.isReachDiscountReached(item)) { return 0; } const itemInfo = this.getSelectItemById(item.id, item.classId); const bigCount = Number(itemInfo.bigCount) || 0; const originalBig = this.toSafeNumber(item.price || item.bigPrice); const reachPrice = this.getItemReachPrice(item); return Math.round(Math.max(0, bigCount * (originalBig - reachPrice)) * 100) / 100; }, getCartItemUnitPrice(item) { if (this.isBouquetItem(item)) { return parseFloat(this.toSafeNumber(item.price || item.bigPrice)); } const itemInfo = this.getSelectItemById(item.id, item.classId); if (Number(itemInfo.bigCount) > 0 && this.isReachDiscountReached(item)) { return parseFloat(this.getItemReachPrice(item)); } if (Number(item.discountPrice) > 0) { return parseFloat(this.toSafeNumber(item.price)); } const parts = this.getLimitBuyPriceDisplayParts(item); return parseFloat(String(parts.main).replace('¥', '')) || 0; }, getCartItemOriginalUnitPrice(item) { if (this.isBouquetItem(item)) { return item.activityType === 'seckill' ? parseFloat(this.toSafeNumber(item.originPrice)) : 0; } if (this.isReachDiscountReached(item)) { return parseFloat(this.toSafeNumber(item.price || item.bigPrice)); } if (Number(item.discountPrice) > 0) { return parseFloat(this.toSafeNumber(item.prePrice)); } const parts = this.getLimitBuyPriceDisplayParts(item); if (parts.showStrike) { return parseFloat(String(parts.strike).replace('¥', '')) || 0; } return 0; }, cartPriceShowStrike(item) { if (this.isBouquetItem(item)) { if (item.activityType !== 'seckill') return false; const original = this.toSafeNumber(item.originPrice); const current = this.toSafeNumber(item.price || item.bigPrice); return original > current; } if (this.isReachDiscountReached(item)) { const original = this.toSafeNumber(item.price || item.bigPrice); const reachPrice = this.getItemReachPrice(item); return reachPrice > 0 && reachPrice < original; } if (Number(item.discountPrice) > 0) { return true; } return this.getLimitBuyPriceDisplayParts(item).showStrike; }, getSelectItemTotalPrice(item) { if (this.isBouquetItem(item)) { const num = Number(item.bigCount) || 0; const price = this.toSafeNumber(item.price || item.bigPrice); return Math.round(num * price * 100) / 100; } return this.getLimitBuyPriceInfo(item).total; }, /** * 购物车中与目标花束行匹配的已有数量(按 id + 规格 + 活动类型分行) * @param {Object} row 待匹配的购物车行结构 * @returns {Number} 已有 bigCount 合计 */ getMatchedBouquetCartCount(row) { if (!row) return 0; const list = Array.isArray(this.selectList) ? this.selectList : []; let count = 0; for (let i = 0; i < list.length; i++) { if (this._selectRowMatches(list[i], row)) { count += Number(list[i].bigCount) || 0; } } return count; }, /** * 校验花束本次数量是否超过商品库存 / 秒杀活动库存 / 秒杀限购。 * existingCount 用于加购合并购物车已有件数。 * activityBoughtCount 为结算失败后回写的历史已购,有值时与本次数量一并计入限购。 * @param {Object} goods 带 stock / activityType / activityLimit / activityStock / activityBoughtCount 的商品或购物车行 * @param {Number} buyNum 本次数量 * @param {Number} existingCount 购物车已有数量,立即购买传 0 * @returns {boolean} 是否通过 */ assertBouquetBuyQty(goods, buyNum, existingCount = 0) { if (!goods) return false; const num = Number(buyNum) || 0; const exist = Number(existingCount) || 0; const total = exist + num; const stockRaw = goods.stock; const hasStock = stockRaw !== undefined && stockRaw !== null && stockRaw !== ''; const stock = Number(stockRaw); const stockSet = Number(goods.stockSet); // 开启库存限制必须校验;未开启时仅在库存是有效数字时校验(避免列表商品缺 stock 被误拦) if (stockSet === 1) { if (!isFinite(stock) || !(stock > 0) || total > stock) { this.$msg('库存不足哦'); return false; } } else if (hasStock && isFinite(stock)) { if (!(stock > 0) || total > stock) { this.$msg('库存不足哦'); return false; } } if (goods.activityType === 'seckill') { const actStockRaw = goods.activityStock; const hasActStock = actStockRaw !== undefined && actStockRaw !== null && actStockRaw !== ''; const actStock = Number(actStockRaw) || 0; if (hasActStock && (!(actStock > 0) || total > actStock)) { this.$msg('库存不足哦'); return false; } const limit = Number(goods.activityLimit) || 0; // 结算失败后回写的已购数量,避免「限购1件且已买过1件」仍能加到购物车 const bought = Number(goods.activityBoughtCount) || 0; if (limit > 0 && (total + bought) > limit) { this.$msg('超过限购数量,每人限购' + limit + '件'); return false; } } return true; }, /** * 组装花束购物车行(property=0):仅做校验并构造行结构,不写入 Vuex/缓存。 * 「立即购买」复用该行结构,保证与加购的计价、展示口径一致,同时不污染购物车。 * 秒杀进行中允许无价格商品按活动价入行,priceType 记为 1,避免结算仍走询价拦截。 * @param {Object} goods 主商品信息 * @param {Object|null} spec 选中的规格子商品,单规格可为 null * @param {Number} num 数量,默认 1 * @returns {Object|null} 构造失败返回 null(已通过 $msg 提示原因) */ buildBouquetRow(goods, spec = null, num = 1) { if (!goods || !goods.id) { this.$msg('商品信息无效'); return null; } const buyNum = Number(num) > 0 ? Number(num) : 1; const saleGoods = spec && spec.id ? spec : goods; const isSeckill = goods.activityType === 'seckill'; let price = Number(saleGoods.price != null ? saleGoods.price : goods.price); // 秒杀进行中:无价格商品用活动价直购;规格自身无价时回退到主商品上已覆盖的秒杀价 if (isSeckill && !(price > 0)) { price = Number(goods.price); } if (isSeckill) { if (!(price > 0)) { this.$msg('商品还没有价格哦'); return null; } } else { // 无价格类型(priceType=0):不能加购,引导向商家询价 if (Number(goods.priceType) === 0) { this.$msg('请向商家咨询价格'); return null; } // 有价格类型且价格为0时,提示商品还没有价格 if ((Number(goods.priceType) === 1 && !(price > 0))) { this.$msg('商品还没有价格哦'); return null; } } const stockRaw = saleGoods.stock != null ? saleGoods.stock : goods.stock; const stockNum = Number(stockRaw); const stockSet = Number(saleGoods.stockSet != null ? saleGoods.stockSet : goods.stockSet) || 0; // 未开启库存限制且没有有效库存时,用 9999 占位,与后端 stockSet=0 的写法一致 const stock = isFinite(stockNum) ? stockNum : (stockSet === 1 ? 0 : 9999); const row = { id: goods.id, goodsId: goods.id, specGoodsId: spec && spec.id ? spec.id : 0, property: 0, classId: 0, name: goods.name || '', itemName: goods.name || '', specName: (spec && spec.specName) || '', cover: goods.smallCover || goods.coverUrl || goods.cover || '', price: price, bigPrice: price, smallPrice: price, priceType: isSeckill ? 1 : goods.priceType, freightType: goods.freightType, weight: saleGoods.weight != null ? saleGoods.weight : (goods.weight || 0), stock: stock, stockSet: stockSet, bigNum: stock > 0 ? stock : 9999, smallNum: 0, bigCount: buyNum, smallCount: 0, ratio: 1, bigUnit: '份', smallUnit: '份' }; // 秒杀商品:打上活动标记与原价,用于购物车/结算页展示划线价; // 实际下单价格由后端独立核对活动配置核价,此处价格仅用于前端展示 if (goods.activityType === 'seckill') { row.activityType = 'seckill'; row.activityEndTime = Number(goods.activityEndTime) || 0; row.originPrice = Number(goods.originPrice) || 0; row.activityLimit = Number(goods.activityLimit) || 0; // 仅在明确带了活动库存时写入,避免列表加购缺该字段时被当成售罄 if (goods.activityStock !== undefined && goods.activityStock !== null && goods.activityStock !== '') { row.activityStock = Number(goods.activityStock) || 0; } } // 立即购买按本次数量校验;加购合并数量在 addBouquetToCart 里再验一次 if (!this.assertBouquetBuyQty(row, buyNum, 0)) { return null; } return row; }, /** * 花束加入购物车(property=0) * @param {Object} goods 主商品信息 * @param {Object|null} spec 选中的规格子商品,单规格可为 null * @param {Number} num 数量,默认 1 */ addBouquetToCart(goods, spec = null, num = 1) { const row = this.buildBouquetRow(goods, spec, num); if (!row) { return false; } const buyNum = Number(row.bigCount) || 1; const existing = this.getMatchedBouquetCartCount(row); // 加购要合并购物车已有件数后再验库存/限购,避免分次加购绕过秒杀限购 if (!this.assertBouquetBuyQty(row, buyNum, existing)) { return false; } const list = Array.isArray(this.selectList) ? [...this.selectList] : []; let found = false; for (let i = 0; i < list.length; i++) { if (this._selectRowMatches(list[i], row)) { list[i] = { ...list[i], ...row, bigCount: (Number(list[i].bigCount) || 0) + buyNum }; found = true; break; } } if (!found) { list.push(row); } this.setSelectInfoByType({ type: this.pageType, info: list }); this.rememberProduct(); if (this.$util && this.$util.hitRemind) { this.$util.hitRemind(); } return true; }, _applyReachDiscountToPriceInfo(item, itemInfo, result) { if (!this.isReachDiscountReached(item)) { result.reachDiscountActive = false; return; } const bigCount = Number(itemInfo.bigCount) || 0; const smallCount = Number(itemInfo.smallCount) || 0; if (!result.isLimitSpecial) { const reachPrice = this.getItemReachPrice(item); const smallPrice = this.toSafeNumber(item.smallPrice); const unitPrice = this.toSafeNumber(item.price || item.bigPrice); result.total = bigCount * reachPrice + smallCount * (smallPrice || unitPrice); } else { const reachNumDiscount = Number(item.reachNumDiscount) || 0; result.total = Math.max(0.01, result.total - reachNumDiscount * bigCount); } result.total = Math.round(result.total * 100) / 100; result.reachDiscountActive = true; }, getLimitBuyPriceInfo(item) { const itemInfo = this.getSelectItemById(item.id, item.classId); const specialPrice = this.toSafeNumber(item.price); const originalPrice = this.toSafeNumber(item.prePrice); const result = { total: 0, specialPrice: specialPrice, originalPrice: originalPrice, exceedNum: 0, limitBuy: 0, hasBuyNum: 0, currentBuyNum: 0, isLimitSpecial: false }; result.total = itemInfo.bigCount * specialPrice + itemInfo.smallCount * originalPrice; const limitItem = this.getLimitBuyItemById(item.id); if (!limitItem || !this.isLimitSpecialItem(item)) { this._applyReachDiscountToPriceInfo(item, itemInfo, result); return result; } const exceedNum = this.toSafeNumber(limitItem.exceedNum) + this.toSafeNumber(limitItem.currentBuyNum); result.exceedNum = exceedNum; result.limitBuy = this.toSafeNumber(limitItem.limitBuy); result.hasBuyNum = this.toSafeNumber(limitItem.hasBuyNum); result.currentBuyNum = this.toSafeNumber(limitItem.currentBuyNum); result.isLimitSpecial = true; if (result.exceedNum <= 0) { result.total = result.currentBuyNum * specialPrice; } else if (result.exceedNum > 0 && result.hasBuyNum > result.limitBuy) { result.total = result.currentBuyNum * originalPrice; } else { result.total = (result.currentBuyNum - result.exceedNum) * specialPrice + result.exceedNum * originalPrice; } this._applyReachDiscountToPriceInfo(item, itemInfo, result); return result; }, getLimitBuyPriceDisplayParts(item) { const priceInfo = this.getLimitBuyPriceInfo(item); const fmt = n => parseFloat(Number(n) || 0); const itemInfo = this.getSelectItemById(item.id, item.classId); if (priceInfo.reachDiscountActive && !priceInfo.isLimitSpecial && Number(itemInfo.bigCount) > 0) { const reachPrice = fmt(this.getItemReachPrice(item)); const originalBig = fmt(item.price || item.bigPrice); return { showStrike: reachPrice < originalBig, main: `¥${reachPrice}`, strike: reachPrice < originalBig ? `¥${originalBig}` : "" }; } if (!priceInfo.isLimitSpecial) { if (Number(item.discountPrice) > 0) { return { showStrike: true, main: `¥${fmt(item.price)}`, strike: `¥${fmt(item.prePrice)}` }; } const big = Number(itemInfo.bigCount) > 0; const p = big ? this.toSafeNumber(item.price || item.bigPrice) : this.toSafeNumber(item.smallPrice); return { showStrike: false, main: `¥${fmt(p)}`, strike: "" }; } if (priceInfo.exceedNum <= 0) { return { showStrike: false, main: `¥${fmt(priceInfo.specialPrice)}`, strike: "" }; } if (priceInfo.exceedNum > 0 && priceInfo.hasBuyNum > priceInfo.limitBuy) { return { showStrike: false, main: `¥${fmt(priceInfo.originalPrice)}`, strike: "" }; } return { showStrike: true, main: `¥${fmt(priceInfo.specialPrice)}`, strike: `¥${fmt(priceInfo.originalPrice)}` }; }, getLimitBuyPriceText(item) { const parts = this.getLimitBuyPriceDisplayParts(item); if (parts.showStrike) { return `${parts.main} ${parts.strike}`; } return parts.main; }, getLimitBuyPriceTip(item) { const priceInfo = this.getLimitBuyPriceInfo(item); if (!priceInfo.isLimitSpecial) { return ""; } if (priceInfo.exceedNum <= 0) { return `限购 ${priceInfo.limitBuy},未超限购,按特价计算`; } if (priceInfo.exceedNum > 0 && priceInfo.hasBuyNum > priceInfo.limitBuy) { return `限购 ${priceInfo.limitBuy},已超出,按原价计算`; } return `限购 ${priceInfo.limitBuy},${priceInfo.currentBuyNum - priceInfo.exceedNum} 扎按特价,超出 ${priceInfo.exceedNum} 扎按原价`; }, //记忆已选的花材 rememberProduct(){ //采购或预订的记忆花材 if(this.pageType == 'cg' || this.pageType == 'bookCg' ){ const account = (this.option && this.option.account) || (this.shopAccount) || (this.account) || uni.getStorageSync('account') || 0 if(!this.$util.isEmpty(account)){ uni.setStorageSync('selectList'+this.pageType+'_hd_'+account, this.selectList) } }else{ uni.setStorageSync('selectList'+this.pageType, this.selectList) } }, //清除已记忆花材 removeMemory(){ uni.removeStorageSync('selectList'+this.pageType) this.resetSelectInfoByType(this.pageType) this.resetLimitBuyInfoByType(this.pageType) if(this.pageType == 'cg' && !this.$util.isEmpty(this.option.account)){ uni.removeStorageSync('selectList'+this.pageType+'_hd_'+this.option.account) } }, async initData(extendInfo) { try { let params = { py: this.py, type: this.type } if (extendInfo) { params = { ...params, ...extendInfo }; } const { data } = await getProductDataApi(params); data.forEach(element => { element.child && element.child.forEach(child => { child.classId = element.classId; child.className = element.className; }); }); this.productInfo = data; if(this.pageType == 'cg' && !this.$util.isEmpty(this.option.account)){ if(uni.getStorageSync('selectList'+this.pageType+'_hd_'+this.option.account)){ let currentInfo = uni.getStorageSync('selectList'+this.pageType+'_hd_'+this.option.account) if(!this.$util.isEmpty(currentInfo)){ this.setSelectInfoByType({ type: this.pageType, info: currentInfo }) }else{ this.resetSelectInfoByType(this.pageType); } }else{ this.resetSelectInfoByType(this.pageType); } } this.classIndex = 0; this.scrollPushList(); // 异步获取并缓存分类节点高度,避免滚动时高频查询 this.$nextTick(() => { setTimeout(() => { const query = uni.createSelectorQuery().in(this); query.selectAll(".selectAll").boundingClientRect(data => { if (data && data.length > 0) { this.cached_top_list = data.map(item => Math.ceil(item.top)); } }).exec(); }, 600); }); } catch (error) { console.log(error) } finally { uni.hideLoading() } }, //滚动或切换分类 获取更多数据 scrollPushList(){ let list = copyObject(this.productInfo); let classList = []; for (let i=0;i { this.scrollTimer = null; // 如果有缓存的高度列表,直接使用缓存进行快速区间判定 if (this.cached_top_list && this.cached_top_list.length > 0) { this.async_detail_msg_fast(options.detail.scrollTop); } else { // 降级容灾:若未获取到缓存,则使用原有的动态查询 this.get_node_details(options); } }, 120); }, // 快速区间判定(无 SelectorQuery 查询,极速响应) async_detail_msg_fast(scrollTop) { let top_page = scrollTop + this.cached_top_list[0]; for(let i = 0; i < this.cached_top_list.length; i++){ let node1 = this.cached_top_list[i]; let node2 = this.cached_top_list[i+1]; if(node2 && top_page >= node1 && top_page < node2){ this.updateActiveClasses(i); break; }else if(node2 && top_page === node2){ this.updateActiveClasses(i + 1); break; } } }, // 动态 DOM 回收与激活核心逻辑 updateActiveClasses(activeIndex) { this.classIndex = activeIndex; // 动态 DOM 回收:只保留当前分类、上一个分类和下两个分类处于激活状态,其余全部释放 if (this.filterProductInfo && this.filterProductInfo.length > 0) { this.filterProductInfo.forEach((item, idx) => { if (idx >= activeIndex - 1 && idx <= activeIndex + 2) { item.isActive = true; } else { item.isActive = false; // 滚出可视区域的分类,销毁其内部所有花材组件,释放内存 } }); this.$forceUpdate(); } }, //获取商品节点信息 get_node_details(options){ const query = uni.createSelectorQuery().in(this); //获得实力 //获取多个节点方式 query.selectAll(".selectAll").boundingClientRect(data=>{ this.top_list = data.map(item=>{ return Math.ceil(item.top); }); this.async_detail_msg(options); }).exec(); }, async_detail_msg(options){ //options 为滚动信息。 options.detail.scrollTop 值为相对于scroll-view。 let top_page = options.detail.scrollTop + this.top_list[0]; for(let i = 0;i < this.top_list.length; i++){ let node1 = this.top_list[i]; let node2 = this.top_list[i+1]; if(node2 && top_page >= node1 && top_page < node2){ this.updateActiveClasses(i); break; }else if(node2 && top_page === node2){ this.updateActiveClasses(i + 1); break; } } }, scroll_bottom(){ this.classIndex = this.filterProductInfo.length-1 this.filterProductInfo[this.classIndex].isActive = true; this.filterProductInfo[this.classIndex-1].isActive = true; }, //获取当前选中商品总价 getSelectItemPrice(item) { let price = 0; const { bigCount, smallCount, bigPrice, smallPrice } = item; let sum = Number(bigCount) * Number(bigPrice) + Number(smallCount) * Number(smallPrice); price = Math.round(sum * 100) / 100; return price; }, //请求成品数据 async initGoodsData(extendInfo) { //extendInfo调用时的扩展参数 如 shopId try { let params = { py: this.py, type: this.type }; if (extendInfo) { params = { ...params, ...extendInfo }; } const { data } = await getGoodsDataApi(params); data.forEach(element => { element.child && element.child.forEach(child => { child.classId = element.classId; child.className = element.className; }); }); this.suitInfo = data; this.suitClassIndex = 0; this.suitScrollPushList(); } catch (error) { } finally { uni.hideLoading(); } }, //成品-滚动或切换分类 获取更多数据 suitScrollPushList(){ let list = copyObject(this.suitInfo); let classList = []; for (let i=0;i this._selectRowMatches(ele, { id, classId })); if (!matches.length) { return info; } const base = { ...matches[0] }; let bigCount = 0; let smallCount = 0; matches.forEach(m => { bigCount += Number(m.bigCount) || 0; smallCount += Number(m.smallCount) || 0; }); return { ...base, bigCount, smallCount, autoPrice: Number(base.autoPrice), itemPrice: Number(base.itemPrice) }; }, //通过id获取当前选中的商品类别信息 左边菜单角标 当前选中该类别商品多少件 getSelectClassById(classId) { let info = { bigCount: 0, //扎数 smallCount: 0 //支数 }; const productItem = this.productInfo && this.productInfo.find(ele => { return ele.classId == classId; }); if (productItem && productItem.child) { for (const item of productItem.child) { for (const selectItem of this.selectList) { if (item.id == selectItem.id && item.classId == selectItem.classId) { info.bigCount += Number(selectItem.bigCount); info.smallCount += Number(selectItem.smallCount); info.itemPrice += selectItem.itemPrice?Number(selectItem.itemPrice):''; } } } } return info; }, //添加商品 addEvent(item) { const list = this.selectList; let hasItem = false; for (let index = 0; index < list.length; index++) { const element = list[index]; // 花束行不与花材合并 if (this.isBouquetItem(element)) { continue; } if (element.id == item.id && element.classId == item.classId) { hasItem = true; //盘点等页面不需要验证库存 if(this.offVerifyRepertory){ list[index] = { ...element, property: 1, bigCount: ++element.bigCount }; }else { list[index] = { ...element, property: 1, bigCount: ++element.bigCount }; if (this.isLimit) { const {bigCount, smallCount} = list[index]; const ratio = Number(item.ratio); if ( Number(bigCount) * ratio + Number(smallCount) > Number(item.bigNum) * ratio + Number(item.smallNum) ) { list[index].bigCount = Number(item.bigNum); list[index].smallCount = Number(item.smallNum); this.$msg("库存还剩"+item.bigNum); return; } } } break; } } if (hasItem == false) { let info = { classId: item.classId, id: item.id }; const classInfo = this.productInfo && this.productInfo.find(element => { return element.classId == item.classId && element.child; }); if (classInfo) { info = classInfo.child.find(ele => { return ele.id == item.id; }); } let params = { ...info, property: 1, bigCount: this.isSmallCount?0:1, smallCount: this.isSmallCount?1:0, autoPrice: 0 } if (info.bigNum && info.bigNum > 0) { list.push(params); } else { //盘点等页面不需要验证库存 if(this.offVerifyRepertory){ list.push(params); }else{ this.$msg("库存不足哦"); return; } } } this.$util.hitRemind(); this.setSelectInfoByType({ type: this.pageType, info: list }); //记忆已经选择的花材 this.rememberProduct() }, addCustomNumEvent(item,params1,type) { const list = this.selectList; let info = { classId: item.classId, id: item.id }; const classInfo = this.productInfo && this.productInfo.find(element => { return element.classId == item.classId && element.child; }); if (classInfo) { info = classInfo.child.find(ele => { return ele.id == item.id; }); } let params = { ...info, bigCount: 0, //扎数 smallCount: 0, //支数 autoPrice: 0 //调价价格 }; list.push(params); if(type!='noAdd'){ this.setSelectInfoByType({ type: this.pageType, info: list }); } this.$nextTick(()=>{ this.customNum(params1) }) //记忆已经选择的花材 this.rememberProduct() }, //减去商品 delEvent(item) { const list = copyObject(this.selectList) for (let index = 0; index < list.length; index++) { let element = list[index]; if (element.id == item.id && element.classId == item.classId) { if (element.bigCount > 0) { if (!this.isSmallCount) { list[index] = {...element, bigCount: --element.bigCount}; } } if (element.smallCount > 0) { if (this.isSmallCount) { list[index] = {...element, smallCount: --element.smallCount}; } } if (element.bigCount == 0 && element.smallCount == 0) { list.splice(index, 1); } } } this.setSelectInfoByType({type: this.pageType, info: list}); this.$util.hitRemind() //记忆已经选择的花材 this.rememberProduct() }, delAllEvent(item) { const list = this.selectList; for (let index = 0; index < list.length; index++) { const element = list[index]; if (this._selectRowMatches(element, item)) { list.splice(index, 1); break; } } this.setSelectInfoByType({ type: this.pageType, info: list }); //记忆已经选择的花材 this.rememberProduct() }, //通过id获取当前选中的商品类别信息 左边菜单角标 当前选中该类别商品多少件 getSuitSelectClassById(classId) { let info = { bigCount: 0, //扎数 smallCount: 0 //支数 }; const productItem = this.suitInfo && this.suitInfo.find(ele => { return ele.classId == classId; }); if (productItem && productItem.child) { for (const item of productItem.child) { for (const selectItem of this.selectList) { if (item.id == selectItem.id && item.classId == selectItem.classId) { info.bigCount += Number(selectItem.bigCount); info.smallCount += Number(selectItem.smallCount); info.itemPrice += selectItem.itemPrice?Number(selectItem.itemPrice):''; } } } } return info; }, //多风格-添加商品 addGoodsEvent(item) { const list = this.selectList; //过滤空数据 let has = false; for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.id == item.id && element.classId == item.classId) { has = true; list[index] = { ...element, bigCount: item.bigCount,goodsStyleSelectIndex: item.goodsStyleSelectIndex }; break; } } if (!has) { let info = { classId: item.classId, id: item.id }; const classInfo = this.suitInfo && this.suitInfo.find(element => { return element.classId == item.classId && element.child; }); if (classInfo) { info = classInfo.child.find(ele => { return ele.id == item.id; }); } let params = { ...info, bigCount: item.bigCount, //扎数 goodsStyleSelectIndex: item.goodsStyleSelectIndex, //选中的风格 }; list.push(params); } this.setSelectInfoByType({ type: this.pageType, info: list }); // this.$forceUpdate(); }, //多风格-添加商品 addGoods(item) { const list = this.selectList; let has = false; for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.id == item.id && element.classId == item.classId) { has = true; list[index] = { ...element, bigCount: ++element.bigCount }; break; } } if (!has) { let info = { classId: item.classId, id: item.id }; const classInfo = this.suitInfo && this.suitInfo.find(element => { return element.classId == item.classId && element.child; }); if (classInfo) { info = classInfo.child.find(ele => { return ele.id == item.id; }); } let params = { ...info, bigCount: 1, //扎数 smallCount: 0, //支数 autoPrice: 0 //调价价格 }; list.push(params); } this.setSelectInfoByType({ type: this.pageType, info: list }); // this.$forceUpdate(); }, //多风格-减去商品 delGoodsEvent(item) { const list = this.selectList; for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.id == item.id && element.classId == item.classId) { if (element.bigCount > 0) { list[index] = { ...element, bigCount: --element.bigCount }; } if (element.bigCount == 0 || !element.bigCount) { list.splice(index, 1); } break; } } this.setSelectInfoByType({ type: this.pageType, info: list }); }, //添加商品 addItemEvent(item) { const list = this.selectList; if(!this.$util.isEmpty(list)){ let hasItem = false for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.id == item.id && element.classId == item.classId) { hasItem = true const { bigCount, smallCount } = list[index]; const ratio = Number(item.ratio); if (this.isLimit) { if ( Number(bigCount) * ratio + Number(smallCount) > Number(item.bigNum) * ratio + Number(item.smallNum) ) { list[index].bigCount = Number(item.bigNum); list[index].smallCount = Number(item.smallNum); list[index].itemPrice = item.itemPrice?Number(item.itemPrice):''; } } list[index] = { ...element, bigCount: Number(item.bigCount), smallCount: Number(item.smallCount), itemPrice: item.itemPrice?Number(item.itemPrice):'' }; break; } } if(hasItem == false){ list.push(item) } }else{ list.push(item) } this.setSelectInfoByType({ type: this.pageType, info: list }); //记忆已经选择的花材 this.rememberProduct() }, //更新商品 updateItemEvent(item) { const list = this.selectList; for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.id == item.id && element.classId == item.classId) { const { bigCount, smallCount } = list[index]; const ratio = Number(item.ratio); if (this.isLimit) { if ( Number(bigCount) * ratio + Number(smallCount) > Number(item.bigNum) * ratio + Number(item.smallNum) ) { list[index].bigCount = Number(item.bigNum); list[index].smallCount = Number(item.smallNum); list[index].itemPrice = item.itemPrice?Number(item.itemPrice):''; } } list[index] = { ...element, bigCount: Number(item.bigCount), smallCount: Number(item.smallCount), itemPrice: item.itemPrice?Number(item.itemPrice):'' }; break; } } this.setSelectInfoByType({ type: this.pageType, info: list }); //记忆已经选择的花材 this.rememberProduct() }, //切换左侧商品类别 swichClass(cur) { // clearInterval(this.timeFun) this.classIndex = cur; this.filterProductInfo[cur].isActive = true; if(cur==this.filterProductInfo.length-1){ this.filterProductInfo[cur-1].isActive = true; } if(cur!=0&&cur!=this.filterProductInfo.length-2){ this.filterProductInfo[cur-1].isActive = true; this.filterProductInfo[cur+1].isActive = true; if(this.filterProductInfo[cur+1].child.length<5&&cur{this.scroll_into_view = 'class_'+cur;}) // this.scrollPushList(); //解决最后一个 ***来回*** 问题 (由于点击左侧导航,右侧锚点位置信息变化,此时滚动事件也随之滚动。) uni.setStorageSync("resolve","last"); setTimeout(()=>{ uni.removeStorageSync("resolve") },400); }, //成品(多风格)-切换左侧商品类别 suitSwichClass(cur) { // clearInterval(this.suitTimeFun) this.suitClassIndex = cur; this.suitFilterProductInfo[cur].isActive = true; if(cur==this.suitFilterProductInfo.length-1){ this.suitFilterProductInfo[cur-1].isActive = true; } if(cur!=0&&cur!=this.suitFilterProductInfo.length-1){ this.suitFilterProductInfo[cur-1].isActive = true; this.suitFilterProductInfo[cur+1].isActive = true; } this.suit_scroll_into_view = ''; this.$nextTick(()=>{this.suit_scroll_into_view = 'class_'+cur;}) // this.suitScrollPushList(); // this.scrollPushList(); //解决最后一个 ***来回*** 问题 (由于点击左侧导航,右侧锚点位置信息变化,此时滚动事件也随之滚动。) uni.setStorageSync("resolve","last"); setTimeout(()=>{ uni.removeStorageSync("resolve") },400); }, //滚动商品监听 suit_scroll_detail(options){ //options 为滚动信息。 options.detail.scrollTop 值为相对于scroll-view。 if(!uni.getStorageSync("resolve")){ this.suit_get_node_details(options); }; }, //获取商品节点信息 suit_get_node_details(options){ const query = uni.createSelectorQuery().in(this); //获得实力 //获取多个节点方式 query.selectAll(".suitSelectAll").boundingClientRect(data=>{ this.suit_top_list = data.map(item=>{ return Math.ceil(item.top); }); this.suit_async_detail_msg(options); }).exec(); }, suit_async_detail_msg(options){ //options 为滚动信息。 options.detail.scrollTop 值为相对于scroll-view。 let top_page = options.detail.scrollTop + this.suit_top_list[0]; for(let i = 0;i < this.suit_top_list.length; i++){ let node1 = this.suit_top_list[i]; let node2 = this.suit_top_list[i+1]; if(node2 && top_page >= node1 && top_page < node2){ this.suitClassIndex = i; this.suitFilterProductInfo[this.suitClassIndex].isActive = true; this.suitFilterProductInfo[this.suitClassIndex+1].isActive = true; // this.suitScrollPushList(); break; }else if(node2 && top_page === node2){ this.suitClassIndex = i + 1; this.suitFilterProductInfo[this.suitClassIndex].isActive = true; this.suitFilterProductInfo[this.suitClassIndex+1].isActive = true; // this.suitScrollPushList(); break; } } }, suit_scroll_bottom(){ this.suitClassIndex = this.suitFilterProductInfo.length-1 this.suitFilterProductInfo[this.suitClassIndex].isActive = true; // this.suitScrollPushList(); }, //搜索对应花材 suitSearchFn() { let list = copyObject(this.suitFilterProductInfo); if(!this.$util.isEmpty(this.py)){ clearInterval(this.suitTimeFun) let commonChildList = []; list.forEach(ele => { //过滤常用 if(ele.classId != -2){ if (!this.$util.isEmpty(ele.child)) { ele.child.forEach(obj => { let hasName = obj.name && obj.name.indexOf(this.py) >= 0; let elePy = (obj.py && obj.py.toLocaleUpperCase()) || ""; let hasPy = elePy.indexOf(this.py.toLocaleUpperCase()) >= 0; if (hasName || hasPy) { if(this.$util.isEmpty(commonChildList)){ commonChildList = [...commonChildList,{classId: ele.classId, className: ele.className,isActive:true,child:[obj]}]; }else{ commonChildList.forEach(res => { if(res.classId==ele.classId){ res.child.push(obj) }else{ commonChildList.push({classId: ele.classId, className: ele.className,isActive:true,child:[obj]}); } }) } } }); } } }); list = this.$util.unique(commonChildList) this.suitFilterProductInfo = list; this.suitClassIndex = 0; this.suit_scroll_into_view = 'class_'+0; }else{ this.suitFilterProductInfo = ''; this.suitClassIndex = 0; this.suit_scroll_into_view = 'class_'+0; this.suitScrollPushList(); } }, searchFn() { let list = copyObject(this.productInfo); if(!this.$util.isEmpty(this.py)){ //大于等于2个字符才开始搜索 shish 20210622 if(this.py.length <=1){ return } //红色粉色紫色绿色白色花材太多,搜索时会卡住,所以设置输入第三个字母时才搜索 // if(this.py.toLocaleLowerCase().indexOf('fs') == 0 && this.py.length <= 2){ // return // } // if(this.py.toLocaleLowerCase().indexOf('hs') == 0 && this.py.length <= 2){ // return // } // if(this.py.toLocaleLowerCase().indexOf('zs') == 0 && this.py.length <= 2){ // return // } // if(this.py.toLocaleLowerCase().indexOf('ls') == 0 && this.py.length <= 2){ // return // } // if(this.py.toLocaleLowerCase().indexOf('bs') == 0 && this.py.length <= 2){ // return // } clearInterval(this.timeFun) let commonChildList = []; list.forEach(ele => { //过滤常用 if(ele.classId != -2){ if (!this.$util.isEmpty(ele.child)) { ele.child.forEach(obj => { //模糊搜索 shish 20210622 let hasName = obj.itemName && obj.itemName.indexOf(this.py) >= 0; let elePy = (obj.py && obj.py.toLocaleUpperCase()) || ""; let hasPy = elePy.indexOf(this.py.toLocaleUpperCase()) >= 0; if (hasName || hasPy) { if(this.$util.isEmpty(commonChildList)){ commonChildList = [...commonChildList,{classId: ele.classId, className: ele.className,isActive:true,child:[obj]}]; }else{ commonChildList.forEach(res => { if(res.classId==ele.classId){ res.child.push(obj) }else{ commonChildList.push({classId: ele.classId, className: ele.className,isActive:true,child:[obj]}); } }) } } }); } } }); list = this.$util.unique(commonChildList) this.filterProductInfo = list; this.classIndex = 0; this.scroll_into_view = 'class_'+0; }else{ this.filterProductInfo = ''; this.classIndex = 0; this.scroll_into_view = 'class_'+0; this.scrollPushList(); } }, //请求课程数据 async initPxClassData() { try { const { data } = await getPxClassDataApi({pageSize:50}); this.pxClassInfo = data.list; } catch (error) { } finally { uni.hideLoading(); } }, } };