mirror of
https://gitee.com/krxd/shuyuan.git
synced 2026-04-08 13:25:54 +08:00
提交最新代码
This commit is contained in:
@@ -1,59 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加购物车
|
|
||||||
*/
|
|
||||||
export function addCart(data : AnyObject) {
|
|
||||||
return request.post(`shop/cart`, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编辑购物车数量
|
|
||||||
*/
|
|
||||||
export function editCart(data : AnyObject) {
|
|
||||||
return request.put(`shop/cart`, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除购物车
|
|
||||||
*/
|
|
||||||
export function deleteCart(data : AnyObject) {
|
|
||||||
return request.put(`shop/cart/delete`, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空购物车
|
|
||||||
*/
|
|
||||||
export function clearCart() {
|
|
||||||
return request.delete(`shop/cart/clear`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取购物车列表
|
|
||||||
*/
|
|
||||||
export function getCartList(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/cart`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取购物车商品列表
|
|
||||||
*/
|
|
||||||
export function getCartGoodsList(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/cart/goods`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取购物车数量
|
|
||||||
*/
|
|
||||||
export function getCartSum(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/cart/sum`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 购物车计算
|
|
||||||
*/
|
|
||||||
export function getCartCalculate(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/cart/calculate`, params)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取发票配置
|
|
||||||
*/
|
|
||||||
export function getInvoiceConfig() {
|
|
||||||
return request.get(`shop/config/invoice`)
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优惠券列表
|
|
||||||
*/
|
|
||||||
export function getShopCouponList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/coupon`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优惠券详情
|
|
||||||
*/
|
|
||||||
export function getShopCouponInfo(id: number) {
|
|
||||||
return request.get(`shop/coupon/${ id }`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优惠券二维码
|
|
||||||
*/
|
|
||||||
export function getShopCouponQrocde(id: number) {
|
|
||||||
return request.get(`shop/coupon/qrcode/${ id }`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 领取优惠券
|
|
||||||
*/
|
|
||||||
export function getCoupon(params: Record<string, any>) {
|
|
||||||
return request.post(`shop/coupon`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取我的优惠券
|
|
||||||
*/
|
|
||||||
export function getMyCouponList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/member/coupon`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取优惠券列表供组件调用
|
|
||||||
*/
|
|
||||||
export function getShopCouponComponents(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/coupon/components`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取我的优惠券数量
|
|
||||||
* status 1:待使用,2:已使用,3:已过期,4:已失效
|
|
||||||
*/
|
|
||||||
export function getMyCouponCount(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/member/coupon/count`, params)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取我的优惠券类型
|
|
||||||
*/
|
|
||||||
export function getMyCouponType() {
|
|
||||||
return request.get(`shop/coupon_type`)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取我的优惠数量
|
|
||||||
*/
|
|
||||||
export function getMyCouponStatusCount() {
|
|
||||||
return request.get(`shop/member/coupon/status_count`)
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取限时折扣轮播
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getActiveDiscountConfig() {
|
|
||||||
return request.get(`shop/discount/config`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取限时折扣列表
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getActiveDiscountList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/discount`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取限时折扣商品列表
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getActiveDiscountGoodsList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/discount/goods`, params)
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品评价
|
|
||||||
*/
|
|
||||||
export function getEvaluateList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/evaluate`,params)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取评价详情
|
|
||||||
*/
|
|
||||||
export function getEvaluateInfo(id:any) {
|
|
||||||
return request.get(`shop/goods/evaluate/${id}`)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 提交评论
|
|
||||||
*/
|
|
||||||
export function setOrderEvaluate(params: Record<string, any>) {
|
|
||||||
return request.post('shop/goods/evaluate', params, {showSuccessMessage: true})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取订单评价
|
|
||||||
*/
|
|
||||||
export function getOrderEvaluate(id: any) {
|
|
||||||
return request.get(`shop/order/evaluate/${id}`)
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品分类模板配置
|
|
||||||
*/
|
|
||||||
export function getGoodsCategoryConfig() {
|
|
||||||
return request.get(`shop/goods/category/config`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品分类树结构
|
|
||||||
*/
|
|
||||||
export function getGoodsCategoryTree() {
|
|
||||||
return request.get(`shop/goods/category/tree`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品分类列表
|
|
||||||
*/
|
|
||||||
export function getGoodsCategoryList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/category/list`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品列表
|
|
||||||
*/
|
|
||||||
export function getGoodsPages(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/pages`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品详情
|
|
||||||
*/
|
|
||||||
export function getGoodsDetail(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/detail`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品规格
|
|
||||||
*/
|
|
||||||
export function getGoodsSku(sku_id: any) {
|
|
||||||
return request.get(`shop/goods/sku/${ sku_id }`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 收藏列表
|
|
||||||
*/
|
|
||||||
export function getCollectList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/collect`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消收藏
|
|
||||||
*/
|
|
||||||
export function cancelCollect(params: Record<string, any>) {
|
|
||||||
return request.put(`shop/goods/collect`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 收藏
|
|
||||||
*/
|
|
||||||
export function collect(goods_id: any) {
|
|
||||||
return request.post(`shop/goods/collect/${ goods_id }`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取评价
|
|
||||||
*/
|
|
||||||
export function getEvaluateList(goods_id: any) {
|
|
||||||
return request.get(`shop/goods/evaluate/list`, { goods_id })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品列表供组件调用
|
|
||||||
*/
|
|
||||||
export function getGoodsComponents(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/components`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品满减信息
|
|
||||||
*/
|
|
||||||
export function getManjian(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/manjian/info`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品足迹添加
|
|
||||||
*/
|
|
||||||
export function browse(params: Record<string, any>) {
|
|
||||||
return request.post(`shop/goods/browse`, params, { showSuccessMessage: false })
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 商品足迹列表
|
|
||||||
*/
|
|
||||||
export function getBrowse(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/goods/browse`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商品足迹删除
|
|
||||||
*/
|
|
||||||
export function delBrowse(params: Record<string, any>) {
|
|
||||||
return request.delete(`shop/goods/browse`, params)
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 分享专区列表
|
|
||||||
export function getNewcomerGoodsList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/newcomer/goods`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNewcomersConfig() {
|
|
||||||
return request.get(`shop/newcomer/config`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 首页新人专享列表
|
|
||||||
export function getNewcomersComponentsList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/newcomer/goods/components`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/***************************************************** 订单列表 ****************************************************/
|
|
||||||
/**
|
|
||||||
* 获取订单设置
|
|
||||||
*/
|
|
||||||
export function getShopOrderConfig() {
|
|
||||||
return request.get(`shop/order/config`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取订单状态列表
|
|
||||||
*/
|
|
||||||
export function getShopOrderStatus() {
|
|
||||||
return request.get(`shop/order/status`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取订单列表
|
|
||||||
*/
|
|
||||||
export function getShopOrder(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/order`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取订单角标数据
|
|
||||||
*/
|
|
||||||
export function getShopOrderNum() {
|
|
||||||
return request.get(`shop/order/num`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取订单详情
|
|
||||||
*/
|
|
||||||
export function getShopOrderDetail(order_id: any) {
|
|
||||||
return request.get(`shop/order/${order_id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭订单
|
|
||||||
*/
|
|
||||||
export function orderClose(order_id: number) {
|
|
||||||
return request.put(`shop/order/close/${order_id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单完成
|
|
||||||
*/
|
|
||||||
export function orderFinish(order_id: number) {
|
|
||||||
return request.put(`shop/order/finish/${order_id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单创建计算
|
|
||||||
*/
|
|
||||||
export function orderCreateCalculate(params: Record<string, any>) {
|
|
||||||
return request.get('shop/order_create/calculate', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单创建
|
|
||||||
*/
|
|
||||||
export function orderCreate(params: Record<string, any>) {
|
|
||||||
return request.post('shop/order_create/create', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询订单可用优惠券
|
|
||||||
*/
|
|
||||||
export function orderCoupon(params: Record<string, any>) {
|
|
||||||
return request.get('shop/order_create/coupon', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询自提点
|
|
||||||
*/
|
|
||||||
export function getStoreList(params: Record<string, any>) {
|
|
||||||
return request.get('shop/order_create/store', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询物流信息
|
|
||||||
*/
|
|
||||||
export function getMaterialflowList(params: Record<string, any>) {
|
|
||||||
return request.get('shop/order/logistics', params)
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取个人积分信息
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getExchangePoint() {
|
|
||||||
return request.get(`shop/exchange/point`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取积分商城推荐列表
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getExchangeComponentsList(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/exchange/components`, params)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取积分商城列表
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getExchangeGoodsList(params : Record<string, any>) {
|
|
||||||
return request.get(`shop/exchange`, params)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取积分商品详情
|
|
||||||
*/
|
|
||||||
export function getExchangeGoodsDetail(id: any) {
|
|
||||||
return request.get(`shop/exchange/goods/${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单创建计算
|
|
||||||
*/
|
|
||||||
export function orderCreateCalculate(params: Record<string, any>) {
|
|
||||||
return request.get('shop/exchange_order/calculate', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单创建
|
|
||||||
*/
|
|
||||||
export function orderCreate(params: Record<string, any>) {
|
|
||||||
return request.post('shop/exchange_order/create', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 榜单分类列表
|
|
||||||
export function getRankList() {
|
|
||||||
return request.get(`shop/rank`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 榜单商品列表
|
|
||||||
export function getRankGoodsList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/rank/goods`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取排行榜配置
|
|
||||||
export function getRankConfig() {
|
|
||||||
return request.get(`shop/rank/getRankConfig`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 榜单组件商品列表
|
|
||||||
export function getRankComponentsGoodsList(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/rank/components`, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 申请退款
|
|
||||||
*/
|
|
||||||
export function applyRefund(params: Record<string, any>) {
|
|
||||||
return request.post(`shop/refund/apply`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改退款申请
|
|
||||||
*/
|
|
||||||
export function editRefund(params: Record<string, any>) {
|
|
||||||
return request.put(`shop/refund/${params.order_refund_no}`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 申请退款退货
|
|
||||||
*/
|
|
||||||
export function refundDelivery(params: Record<string, any>) {
|
|
||||||
return request.post(`shop/refund/delivery/${params.order_refund_no}`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改退款申请
|
|
||||||
*/
|
|
||||||
export function editRefundDelivery(params: Record<string, any>) {
|
|
||||||
return request.put(`shop/refund/delivery/${params.order_refund_no}`, params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取退款原因
|
|
||||||
*/
|
|
||||||
export function getRefundReason() {
|
|
||||||
return request.get('shop/refund/reason')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取退款列表
|
|
||||||
*/
|
|
||||||
export function getRefundList() {
|
|
||||||
return request.get('shop/order/refund')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取退款详情
|
|
||||||
*/
|
|
||||||
export function getRefundDetail(orderRefundNo: string) {
|
|
||||||
return request.get(`shop/order/refund/${orderRefundNo}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取退款金额
|
|
||||||
*/
|
|
||||||
export function getRefundMoney(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/refund/refund_data`,params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编辑退款金额
|
|
||||||
*/
|
|
||||||
export function getRefundMoneyAgain(params: Record<string, any>) {
|
|
||||||
return request.get(`shop/refund/refund_data_by_no`,params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消维权
|
|
||||||
*/
|
|
||||||
export function closeRefund(orderRefundNo: string) {
|
|
||||||
return request.put(`shop/refund/close/${orderRefundNo}`,{}, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取评论设置
|
|
||||||
*/
|
|
||||||
export function getEvaluateConfig() {
|
|
||||||
return request.get(`shop/goods/evaluate/config`)
|
|
||||||
}
|
|
||||||
@@ -1,389 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-skeleton :type="skeleton.type" :loading="skeleton.loading" :config="skeleton.config" v-if="couponList && Object.keys(couponList).length > 0">
|
|
||||||
<view :style="warpCss" class="overflow-hidden">
|
|
||||||
|
|
||||||
<view v-if="diyComponent.style == 'style-1'" class="coupon-wrap style-1 relative">
|
|
||||||
<scroll-view scroll-x="true" class="coupon-list" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/style1_bg2.png') + ')','background-size':'100%','background-repeat':'no-repeat'}">
|
|
||||||
<view class="coupon-class">
|
|
||||||
<block v-if="couponList.length > 1">
|
|
||||||
<view v-for="(item,index) in couponList" :key="index" class="rounded-[16rpx] box-border pt-[14rpx] inline-flex flex-col items-center relative w-[150rpx] h-[130rpx]" :class="{'mr-[20rpx]': index != couponList.length-1}" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/coupon_item_bg.png') + ')','background-size':'100%','background-repeat':'no-repeat'}" @click="couponItemLink(item)">
|
|
||||||
<view class="truncate w-full flex items-baseline justify-center price-font text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[26rpx] font-500">¥</text>
|
|
||||||
<text class="text-[36rpx] truncate font-500">{{ parseFloat(item.price) }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#303133] text-[20rpx] mt-[12rpx]">{{ item.min_condition_money == '0.00' ? '无门槛' : ('满'+parseFloat(item.min_condition_money)+'元可用') }}</view>
|
|
||||||
<view class="mt-[auto] rounded-b-[12rpx] text-[#f2333c] text-[20rpx] w-[100%] h-[36rpx] flex items-center justify-center bg-[#fff5f2]">{{item.type_name}}</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<view v-for="(item,index) in couponList" :key="index" class="rounded-[16rpx] box-border pt-[14rpx] pl-[44rpx] pr-[44rpx] inline-flex items-center justify-between relative w-[100%] h-[130rpx]" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/style1_bg4.png') + ')','background-size':'100%','background-repeat':'no-repeat'}" @click="couponItemLink(item)">
|
|
||||||
<view class="flex price-font text-[var(--price-text-color)] items-baseline">
|
|
||||||
<text class="text-[36rpx] mt-[16rpx] mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[85rpx] font-500 max-w-[170rpx] truncate">{{parseFloat(item.price)}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="border-0 border-dashed border-r-[2rpx] border-[#FF323C] absolute left-[40%] top-[46rpx] bottom-0 w-[2rpx]"></view>
|
|
||||||
<view class="w-[270rpx]">
|
|
||||||
<view class="flex items-center mt-[auto]">
|
|
||||||
<text class="rounded-[4rpx] bg-[#fff3f0] text-[#f2333c] border-[2rpx] border-solid border-[#f2333c] text-[22rpx] px-[6rpx] pb-[4rpx] pt-[6rpx] flex items-center justify-center whitespace-nowrap">{{item.type_name}}</text>
|
|
||||||
<text class="ml-[4rpx] text-[#f2333c] max-w-[184rpx] truncate">{{item.title}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#f2333c] text-[30rpx] font-500 mt-[10rpx] w-[270rpx] truncate">{{item.min_condition_money == '0.00' ? '无门槛' : ('消费满'+parseFloat(item.min_condition_money)+'元可用') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="w-[100%] h-[130rpx] pt-[24rpx] px-[26rpx] box-border flex items-center justify-between absolute left-0 right-0 bottom-0" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/style1_bg.png') + ')','background-size':'100% 130rpx','background-repeat':'no-repeat'}">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<text class="text-[30rpx] text-[#fff] font-400">{{ diyComponent.couponTitle }}</text>
|
|
||||||
<text class="text-[20rpx] text-[rgba(255,255,255,.8)] mt-[10rpx]">{{ diyComponent.couponSubTitle }}</text>
|
|
||||||
</view>
|
|
||||||
<text v-if="diyComponent.btnText" @click="toLink('/addon/shop/pages/coupon/list')" class="bg-[#fff] flex items-center justify-center text-[#FF4142] text-[22rpx] min-w-[100rpx] px-[24rpx] box-border h-[50rpx] coupon-buy-btn">{{diyComponent.btnText}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-else-if="diyComponent.style == 'style-2'" class="coupon-wrap style-2 relative">
|
|
||||||
<scroll-view scroll-x="true" class="coupon-list">
|
|
||||||
<view v-for="(item,index) in couponList" :key="index" class="box-border pt-[14rpx] inline-flex flex-col items-center relative w-[140rpx] h-[130rpx] rounded-[10rpx]" :class="{'mr-[20rpx]': index != couponList.length-1, 'mr-[290rpx]': index == couponList.length-1}" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/coupon_item_bg.png') + ')','background-size':'100%','background-repeat':'no-repeat'}" @click="couponItemLink(item)">
|
|
||||||
<view class="flex items-baseline justify-center w-full truncate price-font text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[38rpx] font-bold truncate">{{parseFloat(item.price)}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#303133] text-[20rpx] truncate max-w-[120rpx] mt-[12rpx]">{{item.min_condition_money == '0.00' ? '无门槛' : ('满'+parseFloat(item.min_condition_money)+'元可用') }}</view>
|
|
||||||
<view class="mt-[auto] rounded-b-[12rpx] text-[#f2333c] text-[20rpx] w-[100%] h-[36rpx] flex items-center justify-center bg-[#fff5f2]">{{item.type_name}}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="w-[290rpx] h-[170rpx] py-[20rpx] pl-[30rpx] box-border flex flex-col items-center justify-between absolute right-0 bottom-0" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/style2_bg.png') + ')','background-size':'290rpx 170rpx','background-repeat':'no-repeat'}">
|
|
||||||
<text class="text-[30rpx] text-[#fff] font-500">{{ diyComponent.couponTitle }}</text>
|
|
||||||
<text class="text-[20rpx] text-[rgba(255,255,255,.8)] mt-[14rpx]">{{ diyComponent.couponSubTitle }}</text>
|
|
||||||
<text v-if="diyComponent.btnText" @click="toLink('/addon/shop/pages/coupon/list')" class="bg-[#fff] text-[#FF4142] text-[22rpx] min-w-[100rpx] px-[24rpx] box-border h-[50rpx] leading-[50rpx] text-center coupon-buy-btn mt-auto">{{diyComponent.btnText}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-else-if="diyComponent.style == 'style-3'" class="coupon-wrap style-3 relative" :style="{'background-image':'url(' + img('addon/shop/diy/goods_coupon/style3_bg.jpg') + ')','background-size':'100% 204rpx','background-repeat':'no-repeat'}">
|
|
||||||
<view class="desc flex flex-col">
|
|
||||||
<text class="text-[30rpx] text-[#fff] font-500">{{ diyComponent.couponTitle }}</text>
|
|
||||||
<text class="text-[22rpx] text-[rgba(255,255,255,.8)] mt-[10rpx]">{{ diyComponent.couponSubTitle }}</text>
|
|
||||||
<text v-if="diyComponent.btnText" @click="toLink('/addon/shop/pages/coupon/list')" class="bg-[#fff] text-[#FF4142] text-[24rpx] w-[140rpx] box-border h-[50rpx] leading-[50rpx] text-center coupon-buy-btn mt-auto">{{diyComponent.btnText}}</text>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="coupon-list" v-if="couponList.length > 1">
|
|
||||||
<view v-for="(item,index) in couponList" :key="index" class="bg-[#fff] box-border p-[8rpx] pb-[12rpx] inline-flex flex-col items-center relative rounded-[20rpx] ml-[12rpx]" @click="couponItemLink(item)">
|
|
||||||
<view class="coupon-item-content">
|
|
||||||
<view class="text-[20rpx] text-[#fff]">{{item.type_name}}</view>
|
|
||||||
<view class="mt-[auto] flex items-baseline justify-center w-full truncate price-font text-[#fff]">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx] font-bold truncate">{{parseFloat(item.price)}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#303133] text-[22rpx] truncate max-w-[120rpx] mt-[12rpx]">{{item.min_condition_money == '0.00' ? '无门槛' : ('满'+parseFloat(item.min_condition_money)+'元可用') }}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view v-if="couponList.length == 1" class="bg-[#fff] box-border p-[10rpx] relative rounded-[20rpx] single-coupon flex-1" @click="couponItemLink(couponList[0])">
|
|
||||||
<view class="flex items-center coupon-item-content">
|
|
||||||
<view class="coupon-left flex items-center justify-center text-[#fff] w-[156rpx] mr-[30rpx]">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx] font-[500]">{{parseFloat(couponList[0].price)}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[#fff] text-[28rpx] mb-[14rpx]">{{couponList[0].min_condition_money == '0.00' ? '无门槛' : ('满'+parseFloat(couponList[0].min_condition_money)+'元可用') }}</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<text class="bg-[#fff] mr-[10rpx] text-[red] text-[20rpx] px-[10rpx] py-[8rpx] rounded-[20rpx]">{{couponList[0].type_name}}</text>
|
|
||||||
<text class="text-[#fff] text-[24rpx]">店铺优惠券</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-else-if="diyComponent.style == 'style-4'" class="coupon-wrap style-4 relative" :style="couponStyle4Css">
|
|
||||||
<view class="desc flex items-center pt-[6rpx] pb-[26rpx]" @click="toLink('/addon/shop/pages/coupon/list')">
|
|
||||||
<text class="text-[32rpx] text-[#fff] font-500" :style="{color: diyComponent.titleColor}">{{ diyComponent.couponTitle }}</text>
|
|
||||||
<text class="text-[22rpx] text-[rgba(255,255,255,.8)] ml-[10rpx]" :style="{color: diyComponent.subTitleColor}">{{ diyComponent.couponSubTitle }}</text>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="coupon-list">
|
|
||||||
<view v-for="(item,index) in couponList" :key="index" class="px-[10rpx] h-[120rpx] inline-flex items-center relative mr-[12rpx] coupon-item box-border min-w-[310rpx]" :style="{'background-color': diyComponent.couponItem.bgColor, 'border-radius': ((diyComponent.couponItem.aroundRadius*2)+'rpx')}" @click="couponItemLink(item)">
|
|
||||||
<view class="flex min-w-[110rpx] max-w-[120rpx] items-baseline justify-center truncate price-font mr-[10rpx]" :style="{'color': diyComponent.couponItem.moneyColor}">
|
|
||||||
<text class="text-[26rpx]">¥</text>
|
|
||||||
<text class="text-[46rpx] font-bold truncate">{{parseFloat(item.price)}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[28rpx] font-500" :style="{'color': diyComponent.couponItem.textColor}">{{item.type_name}}</view>
|
|
||||||
<view class="text-[#666] text-[24rpx] truncate max-w-[180rpx] mt-[12rpx]" :style="{'color': diyComponent.couponItem.subTextColor}">{{item.min_condition_money == '0.00' ? '无门槛' : ('满'+parseFloat(item.min_condition_money)+'元可用') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</x-skeleton>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 优惠券组件
|
|
||||||
import { ref, reactive, computed, watch, onMounted } from 'vue';
|
|
||||||
import { img, redirect } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { useLogin } from '@/hooks/useLogin';
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { getShopCouponComponents,getCoupon } from '@/addon/shop/api/coupon';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
const skeleton = reactive({
|
|
||||||
type: 'banner',
|
|
||||||
loading: false,
|
|
||||||
config: {
|
|
||||||
gridRows: 1,
|
|
||||||
gridRowsGap: '0rpx',
|
|
||||||
headHeight: '170rpx'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const couponStyle4Css = computed(()=>{
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + (diyComponent.value.componentStartBgColor || diyComponent.value.componentEndBgColor) + ';';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const toLink = (url: any)=>{
|
|
||||||
if (diyStore.mode == 'decorate') return;
|
|
||||||
redirect({ url })
|
|
||||||
}
|
|
||||||
|
|
||||||
const couponList: any = ref([])
|
|
||||||
const getShopCouponListFn = () => {
|
|
||||||
let data: object = {
|
|
||||||
num: diyComponent.value.source == 'all' ? diyComponent.value.num : '',
|
|
||||||
coupon_ids: diyComponent.value.source == 'custom' ? diyComponent.value.couponIds : '',
|
|
||||||
};
|
|
||||||
getShopCouponComponents(data).then((res: any) => {
|
|
||||||
couponList.value = res.data
|
|
||||||
skeleton.loading = false;
|
|
||||||
|
|
||||||
// 数据为空时隐藏整个组件
|
|
||||||
// if(couponList.value.length == 0) {
|
|
||||||
// diyComponent.value.pageStyle = '';
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const couponItemLink = (data:any)=> {
|
|
||||||
// redirect({ url: '/addon/shop/pages/coupon/detail', param: { coupon_id: data.id } })
|
|
||||||
collecting(data.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
let obj = {
|
|
||||||
title: '满减券',
|
|
||||||
type_name: '通用券',
|
|
||||||
price: 100,
|
|
||||||
min_condition_money: 0,
|
|
||||||
};
|
|
||||||
for (let i = 0; i < 4; i++) {
|
|
||||||
couponList.value.push(obj);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getShopCouponListFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const collecting = (coupon_id: any) => {
|
|
||||||
if (diyStore.mode == 'decorate') return;
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/coupon/list' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
getCoupon({ coupon_id, number: 1 }).then(res => {
|
|
||||||
// detail.value.btnType = 'using'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.coupon-wrap{
|
|
||||||
&.style-1{
|
|
||||||
.coupon-list{
|
|
||||||
position: relative;
|
|
||||||
height: 270rpx;
|
|
||||||
width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 30rpx 40rpx 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
&::before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 20rpx;
|
|
||||||
right: 20rpx;
|
|
||||||
bottom: 0;
|
|
||||||
background: linear-gradient(#FEF9EC, #FCD9A5);
|
|
||||||
border-radius: 24rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.coupon-buy-btn{
|
|
||||||
border-radius: 50rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.style-2{
|
|
||||||
.coupon-list{
|
|
||||||
position: relative;
|
|
||||||
height: 170rpx;
|
|
||||||
width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 20rpx 0 20rpx 20rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
background: linear-gradient(#EE3928, #EF3F30);
|
|
||||||
}
|
|
||||||
.coupon-buy-btn{
|
|
||||||
border-radius: 50rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.style-3{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20rpx;
|
|
||||||
.desc{
|
|
||||||
padding-top: 12rpx;
|
|
||||||
height: 164rpx;
|
|
||||||
margin-right: 10rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.coupon-list{
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
.coupon-item-content{
|
|
||||||
position: relative;
|
|
||||||
background: linear-gradient( 160deg, #FD5F2F 0%, #F6370F 100%);
|
|
||||||
width: 146rpx;
|
|
||||||
height: 108rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 12rpx 0 14rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
&::after{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border: 12rpx solid #fff;
|
|
||||||
border-right-color: transparent;
|
|
||||||
border-top-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: rotate(45deg) translateY(-50%);
|
|
||||||
right: -5rpx;
|
|
||||||
}
|
|
||||||
&::before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border: 12rpx solid #fff;
|
|
||||||
border-left-color: transparent;
|
|
||||||
border-bottom-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: rotate(45deg) translateY(-50%);
|
|
||||||
left: -22rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.single-coupon{
|
|
||||||
.coupon-item-content{
|
|
||||||
position: relative;
|
|
||||||
background: linear-gradient( 160deg, #FD5F2F 0%, #F6370F 100%);
|
|
||||||
height: 144rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
padding: 12rpx 0 14rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
&::after{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border: 14rpx solid #fff;
|
|
||||||
border-right-color: transparent;
|
|
||||||
border-top-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
left: 139rpx;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
top: -18rpx;
|
|
||||||
}
|
|
||||||
&::before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border: 14rpx solid #fff;
|
|
||||||
border-left-color: transparent;
|
|
||||||
border-bottom-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
left: 139rpx;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
bottom: -16rpx;
|
|
||||||
}
|
|
||||||
.coupon-left{
|
|
||||||
position: relative;
|
|
||||||
&::after{
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 0;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
border-right: 2rpx dashed #fff;
|
|
||||||
width: 2rpx;
|
|
||||||
height: 88rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.coupon-buy-btn{
|
|
||||||
border-radius: 50rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.style-4{
|
|
||||||
padding: 20rpx 24rpx;
|
|
||||||
.coupon-list{
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
.coupon-item{
|
|
||||||
width: calc(50% - 6rpx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,441 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-skeleton :type="skeleton.type" :loading="skeleton.loading" :config="skeleton.config">
|
|
||||||
<view :style="warpCss" class="overflow-hidden">
|
|
||||||
<view :style="maskLayer"></view>
|
|
||||||
<view :class="{'diy-shop-goods-list relative flex flex-wrap justify-between': diyComponent.style != 'style-2', 'biserial-goods-list': diyComponent.style == 'style-2'}">
|
|
||||||
<block v-if="diyComponent.style == 'style-1'">
|
|
||||||
<view class="bg-white w-full flex p-[20rpx] overflow-hidden" :class="{ 'mt-[20rpx]': index > 0 }" :style="itemCss" v-for="(item,index) in goodsList" :key="item.goods_id" @click="toLink(item)">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="200rpx" height="200rpx" :src="img(item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[200rpx] h-[200rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex-1 flex flex-col ml-[20rpx] py-[6rpx] relative">
|
|
||||||
<view class="text-[28rpx] leading-[40rpx] text-[#303133] multi-hidden mb-[10rpx]" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }" v-if="diyComponent.goodsNameStyle.control">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{item.goods_name}}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length && diyComponent.labelStyle.control" class="flex flex-wrap mb-[10rpx]">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="mt-auto flex justify-between items-center">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="flex items-baseline leading-[1]" v-if="diyComponent.priceStyle.control">
|
|
||||||
<view class="font-bold text-[var(--price-text-color)] price-font block truncate max-w-[350rpx]" :style="{ color : diyComponent.priceStyle.color }">
|
|
||||||
<text class="text-[24rpx] font-500 mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2)}}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text v-if="diyComponent.saleStyle.control" class="mt-[8rpx] text-[22rpx] text-[var(--text-color-light9)]" :style="{ color : diyComponent.saleStyle.color }">已售{{item.sale_num}}{{item.unit || '件'}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="diyComponent.btnStyle.control" class="absolute right-[0] bottom-[0]">
|
|
||||||
<view v-if="diyComponent.btnStyle.style == 'button'" :style="goodsBtnCss" class="px-[18rpx] min-w-[100rpx] box-border h-[48rpx] flex items-center justify-center">
|
|
||||||
<text class="text-[20rpx]">{{diyComponent.btnStyle.text}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-else :style="goodsBtnCss" class="w-[50rpx] h-[50rpx] rounded-[50%] flex items-center justify-center">
|
|
||||||
<text :class="[diyComponent.btnStyle.style]" class="nc-iconfont text-[30rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-if="diyComponent.style == 'style-2'">
|
|
||||||
<view>
|
|
||||||
<template v-for="(item,index) in goodsList">
|
|
||||||
<view v-if="(index%2) == 0" class="flex flex-col bg-[#fff] box-border overflow-hidden" :class="{'mt-[24rpx]': index > 1}" :style="itemCss" @click="toLink(item)">
|
|
||||||
<u--image :width="style2Width" :height="style2Width" :src="img(item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image :style="{'width': style2Width,'height': style2Width}" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="relative min-h-[44rpx] px-[16rpx] flex-1 pt-[16rpx] pb-[20rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#303133] leading-[40rpx] text-[28rpx] multi-hidden" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }" v-if="diyComponent.goodsNameStyle.control">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{item.goods_name}}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length && diyComponent.labelStyle.control" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-center mt-[20rpx]">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="flex items-baseline leading-[1]" v-if="diyComponent.priceStyle.control">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font block truncate max-w-[270rpx]" :style="{ color : diyComponent.priceStyle.color }">
|
|
||||||
<text class="text-[24rpx] font-400">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text v-if="diyComponent.saleStyle.control" class="text-[22rpx] mt-[8rpx] text-[var(--text-color-light9)]" :style="{ color : diyComponent.saleStyle.color }">已售{{item.sale_num}}{{item.unit || '件'}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="absolute right-[16rpx] bottom-[16rpx]" v-if="diyComponent.btnStyle.control">
|
|
||||||
<view v-if="diyComponent.btnStyle.style == 'button'" :style="goodsBtnCss" class="px-[18rpx] h-[48rpx] flex items-center justify-center">
|
|
||||||
<text class="text-[20rpx]">{{diyComponent.btnStyle.text}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-else :style="goodsBtnCss" class="w-[46rpx] h-[46rpx] rounded-[50%] flex items-center justify-center">
|
|
||||||
<text :class="[diyComponent.btnStyle.style]" class="nc-iconfont text-[30rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<template v-for="(item,index) in goodsList">
|
|
||||||
<view v-if="(index%2) == 1" class="flex flex-col bg-[#fff] box-border overflow-hidden" :class="{'mt-[24rpx]': index > 1}" :style="itemCss" @click="toLink(item)">
|
|
||||||
<u--image :width="style2Width" :height="style2Width" :src="img(item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image :style="{'width': style2Width,'height': style2Width}" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="relative min-h-[44rpx] px-[16rpx] flex-1 pt-[16rpx] pb-[20rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#303133] leading-[40rpx] text-[28rpx] multi-hidden" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }" v-if="diyComponent.goodsNameStyle.control">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{item.goods_name}}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length && diyComponent.labelStyle.control" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-center mt-[20rpx]">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="flex items-baseline leading-[1]" v-if="diyComponent.priceStyle.control">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font block truncate max-w-[270rpx]" :style="{ color : diyComponent.priceStyle.color }">
|
|
||||||
<text class="text-[24rpx] font-400">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text v-if="diyComponent.saleStyle.control" class="text-[22rpx] mt-[8rpx] text-[var(--text-color-light9)]" :style="{ color : diyComponent.saleStyle.color }">已售{{item.sale_num}}{{item.unit || '件'}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="absolute right-[16rpx] bottom-[16rpx]" v-if="diyComponent.btnStyle.control">
|
|
||||||
<view v-if="diyComponent.btnStyle.style == 'button'" :style="goodsBtnCss" class="px-[18rpx] h-[48rpx] flex items-center justify-center">
|
|
||||||
<text class="text-[20rpx]">{{diyComponent.btnStyle.text}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-else :style="goodsBtnCss" class="w-[46rpx] h-[46rpx] rounded-[50%] flex items-center justify-center">
|
|
||||||
<text :class="[diyComponent.btnStyle.style]" class="nc-iconfont text-[30rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-if="diyComponent.style == 'style-3'">
|
|
||||||
<view :style="style3Css" v-if="goodsList.length">
|
|
||||||
<scroll-view :id="'warpStyle3-'+diyComponent.id" class="whitespace-nowrap min-h-[290rpx]" :scroll-x="true">
|
|
||||||
<view :id="'item'+index+diyComponent.id" class="w-[214rpx] mb-[6rpx] inline-block bg-[#fff] box-border overflow-hidden" :class="{'!mr-[0rpx]' : index == (goodsList.length-1)}" :style="itemCss+itemStyle3" v-for="(item,index) in goodsList" :key="item.goods_id" @click="toLink(item)">
|
|
||||||
<u--image width="214rpx" height="160rpx" :src="img(item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[214rpx] h-[160rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="relative min-h-[40rpx] px-[10rpx] pt-[16rpx] pb-[10rpx]">
|
|
||||||
<view class="text-[26rpx] text-[#303133] truncate" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }" v-if="diyComponent.goodsNameStyle.control">{{item.goods_name}}</view>
|
|
||||||
<view class="text-[var(--price-text-color)] pt-[16rpx] pb-[6rpx] font-bold price-font block truncate max-w-[160rpx] leading-[1] overflow-hidden" :style="{ color : diyComponent.priceStyle.color }" v-if="diyComponent.priceStyle.control">
|
|
||||||
<text class="text-[20rpx] font-400 mr-[2rpx]">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(item)).toFixed(2)}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="diyComponent.btnStyle.control" class="absolute right-[10rpx] bottom-[12rpx]">
|
|
||||||
<view v-if="diyComponent.btnStyle.style != 'button'" :style="goodsBtnCss" class="w-[40rpx] h-[40rpx] rounded-[50%] flex items-center justify-center">
|
|
||||||
<text :class="[diyComponent.btnStyle.style]" class="nc-iconfont text-[28rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</x-skeleton>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 商品列表
|
|
||||||
import { ref,reactive,computed, watch, onMounted, nextTick,getCurrentInstance } from 'vue';
|
|
||||||
import { redirect, img, getToken } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { getGoodsComponents } from '@/addon/shop/api/goods';
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','value']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
const emits = defineEmits(['loadingFn']); //商品数据加载完成之后触发
|
|
||||||
|
|
||||||
const skeleton = reactive({
|
|
||||||
type: '',
|
|
||||||
loading: diyStore.mode == 'decorate' ? false : true,
|
|
||||||
config: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if(props.value) {
|
|
||||||
return props.value;
|
|
||||||
}else if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + (diyComponent.value.componentStartBgColor || diyComponent.value.componentEndBgColor) + ';';
|
|
||||||
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += `background-image:url('${ img(diyComponent.value.componentBgUrl) }');`;
|
|
||||||
style += 'background-size: cover;background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 背景图加遮罩层
|
|
||||||
const maskLayer = computed(()=>{
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += 'position:absolute;top:0;width:100%;';
|
|
||||||
style += `background: rgba(0,0,0,${diyComponent.value.componentBgAlpha / 10});`;
|
|
||||||
style += `height:${height.value}px;`;
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
});
|
|
||||||
|
|
||||||
const itemCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.elementBgColor) style += 'background-color:' + diyComponent.value.elementBgColor + ';';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if(diyComponent.value.style == 'style-2'){
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) style += 'width: calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 20rpx) / 2);'
|
|
||||||
else style += 'width: calc((100vw - 20rpx) / 2 );'
|
|
||||||
}
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsBtnCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.btnStyle.style == 'button' && diyComponent.value.btnStyle.aroundRadius) style += 'border-radius:' + diyComponent.value.btnStyle.aroundRadius * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.btnStyle.startBgColor && diyComponent.value.btnStyle.endBgColor){
|
|
||||||
style += `background:linear-gradient(${diyComponent.value.btnStyle.startBgColor},${diyComponent.value.btnStyle.endBgColor});`;
|
|
||||||
}else{
|
|
||||||
style += 'background-color:' + (diyComponent.value.btnStyle.startBgColor || diyComponent.value.btnStyle.endBgColor) + ';';
|
|
||||||
}
|
|
||||||
if (diyComponent.value.btnStyle.textColor) style += 'color:' + diyComponent.value.btnStyle.textColor + ';';
|
|
||||||
if (diyComponent.value.btnStyle.style == 'button' && diyComponent.value.btnStyle.fontWeight) style += 'font-weight: bold;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const style2Width = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) style += 'calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 20rpx) / 2)'
|
|
||||||
else style += 'calc((100vw - 20rpx) / 2 )'
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const style3Css = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'padding:0 20rpx;';
|
|
||||||
if (diyComponent.value.margin && diyComponent.value.margin.both){style += 'width: calc(100vw - ' + ((diyComponent.value.margin.both * 4) + 40) + 'rpx);'}
|
|
||||||
else{style += 'box-sizing: border-box; width: 100vw;';}
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
//商品样式三
|
|
||||||
const itemStyle3 = ref('');
|
|
||||||
const setItemStyle3 = ()=>{
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
uni.createSelectorQuery().in(instance).select('#warpStyle3-'+diyComponent.value.id).boundingClientRect((res:any) => {
|
|
||||||
uni.createSelectorQuery().in(instance).select('#item0'+diyComponent.value.id).boundingClientRect((data:any) => {
|
|
||||||
itemStyle3.value = `margin-right:${(res.width - data.width*3)/2}px;`
|
|
||||||
}).exec()
|
|
||||||
}).exec()
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
itemStyle3.value= 'margin-right:14rpx;'
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const getGoodsListFn = () => {
|
|
||||||
let data = {
|
|
||||||
num: (diyComponent.value.source == 'all' || diyComponent.value.source == 'category') ? diyComponent.value.num : '',
|
|
||||||
goods_ids: diyComponent.value.source == 'custom' ? diyComponent.value.goods_ids : '',
|
|
||||||
goods_category: diyComponent.value.source == 'category' ? diyComponent.value.goods_category : '',
|
|
||||||
order: diyComponent.value.sortWay
|
|
||||||
}
|
|
||||||
getGoodsComponents(data).then((res) => {
|
|
||||||
goodsList.value = res.data;
|
|
||||||
|
|
||||||
// 数据为空时隐藏整个组件
|
|
||||||
// if(goodsList.value.length == 0 && diyComponent.value.pageStyle) {
|
|
||||||
// diyComponent.value.pageStyle = '';
|
|
||||||
// }
|
|
||||||
|
|
||||||
skeleton.loading = false;
|
|
||||||
emits('loadingFn', res.data)
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
setTimeout(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.diy-shop-goods-list').boundingClientRect((data: any) => {
|
|
||||||
if(data) height.value = data.height;
|
|
||||||
}).exec();
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
nextTick(()=>{
|
|
||||||
setTimeout(()=>{
|
|
||||||
if(diyComponent.value.style == 'style-3') setItemStyle3()
|
|
||||||
},500)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const initSkeleton = ()=> {
|
|
||||||
if (diyComponent.value.style == 'style-1') {
|
|
||||||
|
|
||||||
// 单列 风格
|
|
||||||
skeleton.type = 'list'
|
|
||||||
skeleton.type = 'list'
|
|
||||||
skeleton.config = {
|
|
||||||
textRows: 2
|
|
||||||
};
|
|
||||||
} else if (diyComponent.value.style == 'style-2') {
|
|
||||||
|
|
||||||
// 两列 风格
|
|
||||||
skeleton.type = 'waterfall'
|
|
||||||
skeleton.config = {
|
|
||||||
headHeight: '320rpx',
|
|
||||||
gridRows: 1,
|
|
||||||
textRows: 2,
|
|
||||||
textWidth: ['100%', '80%']
|
|
||||||
};
|
|
||||||
} else if (diyComponent.value.style == 'style-3') {
|
|
||||||
|
|
||||||
// 横向滑动 风格
|
|
||||||
skeleton.type = 'waterfall'
|
|
||||||
skeleton.config = {
|
|
||||||
gridRows: 1,
|
|
||||||
gridColumns: 3,
|
|
||||||
headHeight: '200rpx',
|
|
||||||
textRows: 2,
|
|
||||||
textWidth: ['100%', '80%']
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
const height = ref(0)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if (newValue && newValue.componentName == 'GoodsList') {
|
|
||||||
nextTick(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.diy-shop-goods-list').boundingClientRect((data: any) => {
|
|
||||||
if(data) height.value = data.height;
|
|
||||||
}).exec();
|
|
||||||
if(diyComponent.value.style == 'style-3') setItemStyle3()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
{deep: true}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
let obj = {
|
|
||||||
goods_cover_thumb_mid: "",
|
|
||||||
goods_name: "商品名称",
|
|
||||||
sale_num: "100",
|
|
||||||
unit: "件",
|
|
||||||
goodsSku:{price:100}
|
|
||||||
};
|
|
||||||
goodsList.value.push(obj);
|
|
||||||
goodsList.value.push(obj);
|
|
||||||
nextTick(()=>{
|
|
||||||
if(diyComponent.value.style == 'style-3') setItemStyle3()
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
initSkeleton();
|
|
||||||
getGoodsListFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.goods_id } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
.biserial-goods-list{
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-gap: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="overflow-hidden">
|
|
||||||
<scroll-view scroll-x="true" class="many-goods-list-head" :class="diyComponent.headStyle" :scroll-into-view="'a' + cateIndex" :style="warpCss">
|
|
||||||
<template v-if="diyComponent.headStyle == 'style-3'">
|
|
||||||
<template v-if="diyComponent.source == 'custom'">
|
|
||||||
<view v-for="(item,index) in diyComponent.list" :key="index" :class="['flex-col inline-flex items-center justify-center', { 'pr-[40rpx]': (index != diyComponent.list.length-1) }]" @click="changeCateIndex(item,index)">
|
|
||||||
<image :style="{ borderRadius : (diyComponent.aroundRadius * 2) + 'rpx' }" :class="['w-[90rpx] h-[90rpx] overflow-hidden border-[2rpx] border-solid border-transparent', {'border-[var(--primary-color)]': index == cateIndex }]" v-if="item.imageUrl" :src="img(item.imageUrl)" mode="aspectFit"/>
|
|
||||||
<image :style="{ borderRadius : (diyComponent.aroundRadius * 2) + 'rpx' }" :class="['w-[90rpx] h-[90rpx] overflow-hidden border-[2rpx] border-solid border-transparent', {'border-[var(--primary-color)]': index == cateIndex }]" v-else :src="img('static/resource/images/diy/figure.png')" mode="scaleToFill" />
|
|
||||||
<text :class="['text-[28rpx] mt-[16rpx]', {'font-500 text-[var(--primary-color)]' : index == cateIndex }]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="diyComponent.source == 'goods_category'">
|
|
||||||
<view class="pr-[40rpx] inline-flex flex-col items-center justify-center" @click="changeGoodsCategory({ category_id : 0 })">
|
|
||||||
<image :style="{ borderRadius : (diyComponent.aroundRadius * 2) + 'rpx' }" :class="['w-[90rpx] h-[90rpx] overflow-hidden border-[2rpx] border-solid border-transparent', {'border-[var(--primary-color)]': currentCategoryId == 0}]" :src="img('static/resource/images/diy/figure.png')" mode="scaleToFill" />
|
|
||||||
<text :class="['text-[28rpx] mt-[16rpx]', {'font-500 text-[var(--primary-color)]': currentCategoryId == 0}]">全部</text>
|
|
||||||
</view>
|
|
||||||
<view v-for="(item,index) in goodsCategoryListData" :key="index" :class="['flex-col inline-flex items-center justify-center', { 'pr-[40rpx]': (index != goodsCategoryListData.length-1) }]" @click="changeGoodsCategory(item)">
|
|
||||||
<image :style="{ borderRadius : (diyComponent.aroundRadius * 2) + 'rpx' }" :class="['w-[90rpx] h-[90rpx] overflow-hidden border-[2rpx] border-solid border-transparent', {'border-[var(--primary-color)]': currentCategoryId == item.category_id}]" v-if="item.image" :src="img(item.image)" mode="aspectFit"/>
|
|
||||||
<image :style="{ borderRadius : (diyComponent.aroundRadius * 2) + 'rpx' }" :class="['w-[90rpx] h-[90rpx] overflow-hidden border-[2rpx] border-solid border-transparent', {'border-[var(--primary-color)]': currentCategoryId == item.category_id}]" v-else :src="img('static/resource/images/diy/figure.png')" mode="scaleToFill" />
|
|
||||||
<text :class="['text-[28rpx] mt-[16rpx]', {'font-500 text-[var(--primary-color)]' : currentCategoryId == item.category_id}]">{{ item.category_name }}</text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<view v-for="(item, index) in diyComponent.list" class="scroll-item" :class="[diyComponent.headStyle, { active: index == cateIndex }]" :id="'a' + index" :key="index" @click="changeCateIndex(item, index)">
|
|
||||||
<view class="cate" v-if="diyComponent.headStyle == 'style-1'">
|
|
||||||
<view class="name">{{ item.title }}</view>
|
|
||||||
<view class="desc" :v-if="item.desc">{{ item.desc }}</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="diyComponent.headStyle == 'style-2'" class="cate">
|
|
||||||
<view class="name">{{ item.title }}</view>
|
|
||||||
<text class="nc-iconfont nc-icon-xiaolian-2 !text-[40rpx] text-[var(--primary-color)] transform" v-if="index == cateIndex"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="diyComponent.headStyle == 'style-4'" class="cate">
|
|
||||||
<view class="name">{{ item.title }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<diy-goods-list class="many-goods-list-body" v-if="goodsValue" :value="goodsValue"></diy-goods-list>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 多商品组 组件
|
|
||||||
import { ref, computed, watch, onMounted } from 'vue';
|
|
||||||
import { img } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import diyGoodsList from '@/addon/shop/components/diy/goods-list/index.vue';
|
|
||||||
import { getGoodsCategoryList } from '@/addon/shop/api/goods';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if (newValue && newValue.componentName == 'ManyGoodsList') {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if(diyComponent.value.headStyle == 'style-3' && diyComponent.value.source == 'goods_category' && diyComponent.value.goods_category){
|
|
||||||
getGoodsCategoryFn(diyComponent.value.goods_category);
|
|
||||||
}else{
|
|
||||||
changeCateIndex(diyComponent.value.list[0], 0,true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cateIndex = ref(0) // 当前选中的分类id
|
|
||||||
|
|
||||||
const goodsValue:any = ref(null);
|
|
||||||
|
|
||||||
const changeCateIndex = (item:any, index:any, isFirst:any = false)=> {
|
|
||||||
// 装修模式禁止跳转
|
|
||||||
if (diyStore.mode == 'decorate' && !isFirst) return;
|
|
||||||
|
|
||||||
cateIndex.value = index;
|
|
||||||
refreshGoodsList({
|
|
||||||
source: item.source,
|
|
||||||
goods_category: item.goods_category,
|
|
||||||
goods_ids: item.goods_ids
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsCategoryListData = ref([])
|
|
||||||
const currentCategoryId = ref(0) // 当前选中的分类id
|
|
||||||
|
|
||||||
// 获取商品分类列表
|
|
||||||
const getGoodsCategoryFn = (pid:any)=> {
|
|
||||||
getGoodsCategoryList({
|
|
||||||
pid
|
|
||||||
}).then(res => {
|
|
||||||
if (res.code == 1) {
|
|
||||||
goodsCategoryListData.value = res.data;
|
|
||||||
if (goodsCategoryListData.value) {
|
|
||||||
refreshGoodsList({
|
|
||||||
source: 'category',
|
|
||||||
goods_category: ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换商品分类,查询商品列表数据
|
|
||||||
const changeGoodsCategory = (item :any)=> {
|
|
||||||
// 装修模式禁止跳转
|
|
||||||
if (diyStore.mode == 'decorate') return;
|
|
||||||
currentCategoryId.value = item.category_id
|
|
||||||
refreshGoodsList({
|
|
||||||
source: 'category',
|
|
||||||
goods_category: currentCategoryId.value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const refreshGoodsList = (obj:any)=> {
|
|
||||||
goodsValue.value = {
|
|
||||||
style: diyComponent.value.style,
|
|
||||||
margin: diyComponent.value.margin,
|
|
||||||
source: obj.source,
|
|
||||||
|
|
||||||
num: diyComponent.value.num,
|
|
||||||
sortWay: diyComponent.value.sortWay,
|
|
||||||
|
|
||||||
goodsNameStyle: diyComponent.value.goodsNameStyle,
|
|
||||||
priceStyle: diyComponent.value.priceStyle,
|
|
||||||
saleStyle: diyComponent.value.saleStyle,
|
|
||||||
btnStyle: diyComponent.value.btnStyle,
|
|
||||||
labelStyle: diyComponent.value.labelStyle,
|
|
||||||
|
|
||||||
elementBgColor: diyComponent.value.elementBgColor,
|
|
||||||
topElementRounded: diyComponent.value.topElementRounded,
|
|
||||||
bottomElementRounded: diyComponent.value.bottomElementRounded
|
|
||||||
};
|
|
||||||
|
|
||||||
if (obj.goods_category) {
|
|
||||||
goodsValue.value.goods_category = obj.goods_category
|
|
||||||
}
|
|
||||||
if (obj.goods_ids && obj.goods_ids.length) {
|
|
||||||
goodsValue.value.goods_ids = obj.goods_ids
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.many-goods-list-head {
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 5;
|
|
||||||
width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20rpx 0 10rpx;
|
|
||||||
margin-bottom:20rpx;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&.style-1{
|
|
||||||
padding: 26rpx 0 14rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.style-2{
|
|
||||||
height: 100rpx;
|
|
||||||
padding: 20rpx 0 16rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.style-3{
|
|
||||||
padding: 26rpx 20rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
width: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.style-4{
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-item {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
width: auto;
|
|
||||||
padding: 0 20rpx;
|
|
||||||
|
|
||||||
&.style-1{
|
|
||||||
&:first-child {
|
|
||||||
width: calc(25% - 20rpx);
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
.name{
|
|
||||||
color: var(--primary-color);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.desc {
|
|
||||||
color: #ffffff;
|
|
||||||
border-radius: 20rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cate {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desc {
|
|
||||||
font-size: 22rpx;
|
|
||||||
color: #999;
|
|
||||||
height: 38rpx;
|
|
||||||
line-height: 38rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 10rpx;
|
|
||||||
min-width: 110rpx;
|
|
||||||
max-width: 220rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
padding: 0 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.style-2{
|
|
||||||
.cate{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.name{
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
line-height: 32rpx;
|
|
||||||
}
|
|
||||||
&.active {
|
|
||||||
.name{
|
|
||||||
color:var(--primary-color);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.nc-iconfont{
|
|
||||||
position: absolute;
|
|
||||||
bottom: -35rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.style-4{
|
|
||||||
padding: 0 10rpx 14rpx;
|
|
||||||
.cate{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 10rpx 12rpx;
|
|
||||||
background-color: #F6F6F6;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
min-width: 136rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 2rpx solid #F6F6F6;
|
|
||||||
}
|
|
||||||
.name{
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
line-height: 32rpx;
|
|
||||||
}
|
|
||||||
&.active {
|
|
||||||
.cate{
|
|
||||||
background-color: var(--primary-color-light);
|
|
||||||
border-color: var(--primary-color);
|
|
||||||
position: relative;
|
|
||||||
&::after{
|
|
||||||
content: "";
|
|
||||||
width: 18rpx;
|
|
||||||
height: 18rpx;
|
|
||||||
position: absolute;
|
|
||||||
background-color: var(--primary-color-light);
|
|
||||||
border: 2rpx solid transparent;
|
|
||||||
border-bottom-color: var(--primary-color);
|
|
||||||
border-right-color: var(--primary-color);
|
|
||||||
bottom: -12rpx;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%) rotate(45deg);
|
|
||||||
border-bottom-right-radius: 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.name{
|
|
||||||
color: var(--primary-color);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.nc-iconfont{
|
|
||||||
position: absolute;
|
|
||||||
bottom: -35rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-skeleton :type="skeleton.type" :loading="skeleton.loading" :config="skeleton.config">
|
|
||||||
<view class="overflow-hidden" :style="warpCss">
|
|
||||||
<view :style="maskLayer"></view>
|
|
||||||
<view class="diy-shop-exchange-goods-list relative flex flex-wrap justify-between" v-if="goodsList.length">
|
|
||||||
<view class="overflow-hidden bg-[#fff] flex flex-col box-border w-[calc(50%-10rpx)] rounded-[var(--rounded-mid)]" :class="{'mt-[20rpx]': index > 1}" :style="itemCss" v-for="(item,index) in goodsList" :key="item.goods_id" @click="toLink(item)">
|
|
||||||
<u--image :width="style2Width" :height="style2Width" radius="var(--rounded-mid)" :src="img(item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="rounded-[var(--rounded-mid)] overflow-hidden" :style="{'width': style2Width,'height': style2Width}" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex-1 pt-[10rpx] pb-[20rpx] px-[16rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#333] leading-[40rpx] text-[28rpx] multi-hidden" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }">{{item.names}}</view>
|
|
||||||
<view class="text-[22rpx] leading-[28rpx] mt-[10rpx] text-[var(--text-color-light9)]" :style="{ color : diyComponent.saleStyle.color }">已兑{{item.total_exchange_num}}人</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-center mt-[16rpx]" >
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view :style="{ color : diyComponent.priceStyle.mainColor }" class="text-[var(--price-text-color)] price-font ml-[2rpx] flex items-baseline">
|
|
||||||
<text class="text-[32rpx]">{{ item.point }}</text>
|
|
||||||
<text class="text-[24rpx] ml-[4rpx]">积分</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.price&&item.price>0" class="flex items-center mt-[6rpx] price-font">
|
|
||||||
<text :style="{ color : diyComponent.priceStyle.mainColor }" class="text-[#333] font-400 text-[32rpx]">+{{ parseFloat(item.price).toFixed(2) }}</text>
|
|
||||||
<text :style="{ color : diyComponent.priceStyle.mainColor }" class="text-[var(--price-text-color)] font-400 ml-[4rpx] text-[24rpx]">元</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[120rpx] h-[54rpx] text-[22rpx] flex-center !text-[#fff] m-0 rounded-full primary-btn-bg remove-border text-center" shape="circle">去兑换</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-else-if="!goodsList.length" class="empty-page">
|
|
||||||
<image class="img" :src="img('static/resource/images/system/empty.png')" model="aspectFit" />
|
|
||||||
<view class="desc">暂无商品</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</x-skeleton>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 积分商品列表
|
|
||||||
import { ref,reactive,computed, watch, onMounted, nextTick,getCurrentInstance } from 'vue';
|
|
||||||
import { redirect, img } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { getExchangeComponentsList } from '@/addon/shop/api/point';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','value']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const skeleton = reactive({
|
|
||||||
type: '',
|
|
||||||
loading: diyStore.mode == 'decorate' ? false : true,
|
|
||||||
config: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if(props.value) {
|
|
||||||
return props.value;
|
|
||||||
}else if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += `background-image:url('${ img(diyComponent.value.componentBgUrl) }');`;
|
|
||||||
style += 'background-size: cover;background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 背景图加遮罩层
|
|
||||||
const maskLayer = computed(()=>{
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += 'position:absolute;top:0;width:100%;';
|
|
||||||
style += `background: rgba(0,0,0,${diyComponent.value.componentBgAlpha / 10});`;
|
|
||||||
style += `height:${height.value}px;`;
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
});
|
|
||||||
|
|
||||||
const itemCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const style2Width = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) style += 'calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 20rpx) / 2)'
|
|
||||||
else style += 'calc((100vw - 20rpx) / 2 )'
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const getGoodsListFn = () => {
|
|
||||||
let data = {
|
|
||||||
order: diyComponent.value.sortWay,
|
|
||||||
num: diyComponent.value.source == 'all' ? diyComponent.value.num : '',
|
|
||||||
ids: diyComponent.value.source == 'custom' ? diyComponent.value.goods_ids.join(',') : '',
|
|
||||||
}
|
|
||||||
getExchangeComponentsList(data).then((res) => {
|
|
||||||
goodsList.value = res.data;
|
|
||||||
skeleton.loading = false;
|
|
||||||
|
|
||||||
// 数据为空时隐藏整个组件
|
|
||||||
// if(goodsList.value.length == 0) {
|
|
||||||
// diyComponent.value.pageStyle = '';
|
|
||||||
// }
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
setTimeout(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.diy-shop-exchange-goods-list').boundingClientRect((data: any) => {
|
|
||||||
height.value = data.height;
|
|
||||||
}).exec();
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const initSkeleton = ()=> {
|
|
||||||
if (diyComponent.value.style == 'style-1') {
|
|
||||||
|
|
||||||
// 单列 风格
|
|
||||||
skeleton.type = 'list'
|
|
||||||
skeleton.type = 'list'
|
|
||||||
skeleton.config = {
|
|
||||||
textRows: 2
|
|
||||||
};
|
|
||||||
} else if (diyComponent.value.style == 'style-2') {
|
|
||||||
|
|
||||||
// 两列 风格
|
|
||||||
skeleton.type = 'waterfall'
|
|
||||||
skeleton.config = {
|
|
||||||
headHeight: '320rpx',
|
|
||||||
gridRows: 1,
|
|
||||||
textRows: 2,
|
|
||||||
textWidth: ['100%', '80%']
|
|
||||||
};
|
|
||||||
} else if (diyComponent.value.style == 'style-3') {
|
|
||||||
|
|
||||||
// 横向滑动 风格
|
|
||||||
skeleton.type = 'waterfall'
|
|
||||||
skeleton.config = {
|
|
||||||
gridRows: 1,
|
|
||||||
gridColumns: 3,
|
|
||||||
headHeight: '200rpx',
|
|
||||||
textRows: 2,
|
|
||||||
textWidth: ['100%', '80%']
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
const height = ref(0)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if (newValue && newValue.componentName == 'ShopExchangeGoods') {
|
|
||||||
nextTick(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.diy-shop-exchange-goods-list').boundingClientRect((data: any) => {
|
|
||||||
height.value = data.height;
|
|
||||||
}).exec();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
{deep: true}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
let obj = {
|
|
||||||
image: "",
|
|
||||||
names: "商品名称",
|
|
||||||
total_exchange_num: 100,
|
|
||||||
point: 100,
|
|
||||||
price:100
|
|
||||||
};
|
|
||||||
goodsList.value.push(obj);
|
|
||||||
goodsList.value.push(obj);
|
|
||||||
}else{
|
|
||||||
initSkeleton();
|
|
||||||
getGoodsListFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/point/detail', param: { id: data.id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss" class="shop-exchange-info-wrap">
|
|
||||||
<view class="pl-[60rpx] pt-[71rpx] pb-[133rpx] min-h-[382rpx] box-border text-[#fff]">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view :style="navbarInnerStyle"></view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<template v-if="token">
|
|
||||||
<view class="text-[34rpx] leading-[48rpx]">我的积分</view>
|
|
||||||
<view class="text-[80rpx] font-500 price-font leading-[112rpx]">{{memberPoint.point||0}}</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx]">今日获得:{{memberPoint.today_point||0}}</view>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<view class="pt-[42rpx] title">积分当钱花</view>
|
|
||||||
<view class="text-[26rpx] leading-[36rpx] text-[#FEF2C0] mt-[10rpx]">做任务可领积分</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, ref, watch,onMounted } from 'vue'
|
|
||||||
import { getExchangePoint } from '@/addon/shop/api/point';
|
|
||||||
import { img, getToken } from '@/utils/common';
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import useDiyStore from '@/app/stores/diy'
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','global']);
|
|
||||||
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
const loading = ref(true)
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.bgUrl) {
|
|
||||||
style += 'background-image:url(' + img(diyComponent.value.bgUrl) + ');';
|
|
||||||
style += 'background-size: 100%;';
|
|
||||||
style += 'backgroundPosition: bottom;';
|
|
||||||
style += 'background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},{deep: true})
|
|
||||||
|
|
||||||
const memberPoint :Record<string, any> = ref({})
|
|
||||||
|
|
||||||
const token = ref(getToken())
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
memberPoint.value = {
|
|
||||||
point: 10500,
|
|
||||||
today_point: 500,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!token) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getExchangePointFn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getExchangePointFn= async()=> {
|
|
||||||
const res = await getExchangePoint()
|
|
||||||
memberPoint.value = res.data
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 导航栏内部盒子的样式
|
|
||||||
const navbarInnerStyle = computed(() => {
|
|
||||||
let style = '';
|
|
||||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
|
||||||
// #ifdef MP
|
|
||||||
if (props.global.topStatusBar.isShow == false) {
|
|
||||||
style += 'height:' + menuButtonInfo.height + 'px;';
|
|
||||||
style += 'padding-top:' + menuButtonInfo.top + 'px;';
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.title{
|
|
||||||
width: 240rpx;
|
|
||||||
height: 58rpx;
|
|
||||||
font-family: FZLanTingHei-EB-GBK, FZLanTingHei-EB-GBK;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 48rpx;
|
|
||||||
line-height: 56rpx;
|
|
||||||
text-align: left;
|
|
||||||
color: transparent;
|
|
||||||
background: linear-gradient(90.00002732075491deg, #FFFDF0 5%, #FEF1B9 88%);
|
|
||||||
-webkit-background-clip: text; /* 确保背景色可以应用到文字上 */
|
|
||||||
background-clip: text;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss" class="overflow-hidden">
|
|
||||||
<scroll-view scroll-x="true" class="w-[100%] whitespace-nowrap">
|
|
||||||
<view class="flex items-start">
|
|
||||||
<view class="inline-block" v-for="(item,index) in diyComponent.list" :key="index">
|
|
||||||
<view class="w-[460rpx] px-[20rpx] pb-[20rpx] pt-[20rpx] flex flex-col items-start" :class="{'mr-[20rpx]': (diyComponent.list.length-1) != index}" :style="swiperItemCss(item)" v-if="listGoods[item.rankIds[0]] && listGoods[item.rankIds[0]].length > 0">
|
|
||||||
<view class="flex items-center h-[50rpx]">
|
|
||||||
<image class="w-[30rpx] h-[30rpx] mr-[10rpx]" v-if="item.imgUrl" :src="img(item.imgUrl)" mode="aspectFill"></image>
|
|
||||||
<view :style="{'color': item.textColor}">
|
|
||||||
<text class="text-[30rpx] font-bold" v-if="item.text">{{ item.text }}</text>
|
|
||||||
<text class="text-[30rpx] font-bold" v-else>{{ listGoodsNames[item.rankIds[0]] }}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="mb-[6rpx] h-[35rpx]" :style="{'color': item.subTitle.textColor}" @click="diyStore.toRedirect(item.subTitle.link)">
|
|
||||||
<text class="text-[24rpx]" v-if="item.subTitle.text">{{item.subTitle.text}}</text>
|
|
||||||
<text class="iconfont iconyouV6xx !text-[24rpx]" v-if="item.subTitle.text"></text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[30rpx]">
|
|
||||||
<view class="flex bg-[#fff] p-[10rpx] rounded-[16rpx] mb-[16rpx]" v-for="(goods, gIndex) in listGoods[item.rankIds[0]]" :class="{'mb-0': gIndex === listGoods[item.rankIds[0]].length - 1}" @click="toDetail(goods.goods_id)">
|
|
||||||
<view class="relative w-[130rpx] h-[130rpx] mr-[16rpx]">
|
|
||||||
<image class="absolute top-[6rpx] left-[8rpx] w-[30rpx] h-[36rpx]" :style="{ zIndex:2 }" :src="getRankBadge(goods.rank_num)" mode="aspectFill"></image>
|
|
||||||
<view class="absolute top-[2rpx] left-[-3rpx] flex items-center justify-center w-[50rpx] h-[50rpx]" :style="{ zIndex: 3 }">
|
|
||||||
<text class="text-[20rpx] font-bold text-[#fff]">{{ goods.rank_num }}</text>
|
|
||||||
</view>
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="130rpx" height="130rpx" :src="img(goods.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[130rpx] h-[130rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="leading-[1.3] multi-hidden w-[290rpx] text-[28rpx] whitespace-normal">{{goods.goods_name}}</view>
|
|
||||||
<view class="flex items-center justify-between mt-[auto]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font flex items-baseline">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ diyGoods.goodsPrice(goods).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ diyGoods.goodsPrice(goods).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<text class="iconfont icongouwuche3 text-[var(--primary-color)] border-[2rpx] border-solid border-[var(--primary-color)] rounded-[50%] text-[22rpx] p-[6rpx]"></text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
// 排行榜
|
|
||||||
import { ref,reactive,computed, watch, onMounted } from 'vue';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { redirect, img } from '@/utils/common';
|
|
||||||
import { getRankComponentsGoodsList } from '@/addon/shop/api/rank'
|
|
||||||
import { useGoods } from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount']);
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const swiperItemCss = (data: any)=> {
|
|
||||||
var style = '';
|
|
||||||
if (data.listFrame.startColor) {
|
|
||||||
if (data.listFrame.startColor && data.listFrame.endColor) style += 'background: linear-gradient(90deg, ' + data.listFrame.startColor + ', ' + data.listFrame.endColor + ');';
|
|
||||||
else style = 'background-color:' + data.listFrame.startColor + ';';
|
|
||||||
}
|
|
||||||
if (data.bgUrl) {
|
|
||||||
style += 'background-image:' + 'url(' + img(data.bgUrl) + ');';
|
|
||||||
style += 'background-size: 100%;';
|
|
||||||
style += 'background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},{deep: true})
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
if(diyComponent.value.componentName == 'ShopGoodsRanking') {
|
|
||||||
const fakeGoods = {
|
|
||||||
goods_name: '商品名称',
|
|
||||||
goods_cover_thumb_mid: '',
|
|
||||||
goodsSku: {
|
|
||||||
price: 10
|
|
||||||
},
|
|
||||||
rank_num: 0 // 初始化为 0,后续会递增
|
|
||||||
};
|
|
||||||
diyComponent.value.list.forEach(item => {
|
|
||||||
if (!item.goodsList) {
|
|
||||||
item.goodsList = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.goodsList.length === 0) {
|
|
||||||
const fakeGoodsList = [];
|
|
||||||
// 生成三个商品,并为每个商品的 rank_num 递增
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
const newItem = { ...fakeGoods, rank_num: i + 1 }; // rank_num 从 1 开始递增
|
|
||||||
fakeGoodsList.push(newItem);
|
|
||||||
}
|
|
||||||
listGoods[item.rankIds[0]] = fakeGoodsList;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getRankGoodsListFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const listGoods = reactive({});
|
|
||||||
const listGoodsNames = reactive({});
|
|
||||||
const getRankGoodsListFn = () => {
|
|
||||||
diyComponent.value.list.forEach((item) => {
|
|
||||||
const rank_id = Array.isArray(item.rankIds) ? item.rankIds[0] : 0;
|
|
||||||
const data = {
|
|
||||||
rank_id: item.source === 'custom' ? rank_id : 0
|
|
||||||
};
|
|
||||||
getRankComponentsGoodsList(data).then((res) => {
|
|
||||||
if (res.data && res.data.goods_list.length > 0) {
|
|
||||||
listGoods[item.rankIds[0]] = res.data.goods_list;
|
|
||||||
listGoodsNames[item.rankIds[0]] = res.data.name;
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error('获取商品数据失败:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function getRankBadge(sort: any) {
|
|
||||||
switch (sort) {
|
|
||||||
case 1:
|
|
||||||
return img('addon/shop/rank/rank_first.png');
|
|
||||||
case 2:
|
|
||||||
return img('addon/shop/rank/rank_second.png');
|
|
||||||
case 3:
|
|
||||||
return img('addon/shop/rank/rank_third.png');
|
|
||||||
default:
|
|
||||||
return img('addon/shop/rank/rank.png');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const toDetail = (id: string | number) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: id }, mode: 'navigateTo' })
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-skeleton :type="skeleton.type" :loading="skeleton.loading" :config="skeleton.config">
|
|
||||||
<view :style="warpCss" v-if="goodsNum">
|
|
||||||
<view class="w-full">
|
|
||||||
<scroll-view :id="'warpStyle-'+diyComponent.id" class="whitespace-nowrap h-[341rpx] w-full" :scroll-x="true">
|
|
||||||
<block v-for="(item,index) in goodsList" :key="index">
|
|
||||||
<view v-if="item.info" :id="'item'+index+diyComponent.id" class="w-[224rpx] h-[341rpx] mr-[20rpx] inline-block bg-[#fff] box-border overflow-hidden" :class="{'!mr-[0rpx]' : index == (goodsList.length-1)}" :style="itemCss+itemStyle" @click="toLink(item)">
|
|
||||||
<view class="w-full h-[134rpx]" :style="listFrameStyle(item)">
|
|
||||||
<view class="flex pl-[16rpx] pr-[20rpx] justify-between h-[63rpx] items-center">
|
|
||||||
<view class="text-[28rpx] leading-[34rpx] flex-1 mr-[8rpx]" :style="{'color':item.title.textColor}">{{item.title.text}}</view>
|
|
||||||
<view class="w-[68rpx] h-[34rpx] text-[22rpx] text-center leading-[34rpx] text-[#fff] rounded-[17rpx]" :style="moreTitleStyle(item)">{{item.moreTitle.text}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[-71rpx] h-[278rpx] w-full px-[20rpx] pt-[18rpx] box-border bg-white" :style="itemCss">
|
|
||||||
<view class="flex items-center justify-center w-[184rpx] h-[184rpx]">
|
|
||||||
<u--image width="184rpx" height="184rpx" :radius="'var(--goods-rounded-small)'" :src="img(item.info.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[184rpx] h-[184rpx] rounded-[var(--goods-rounded-small)]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="pt-[12rpx]">
|
|
||||||
<view class="h-[44rpx] pl-[4rpx] min-w-[168rpx] box-border flex justify-between items-center mx-auto border-[2rpx] border-solid border-[var(--primary-color)] rounded-[20rpx]" :style="{'border-color':item.button.color}">
|
|
||||||
<view class="text-[var(--price-text-color)] font-bold price-font flex items-baseline leading-[40rpx] flex-1 justify-center" >
|
|
||||||
<view class="leading-[1] max-w-[105rpx] truncate" :style="{ color : diyComponent.priceStyle.mainColor }">
|
|
||||||
<text class="text-[18rpx] font-400 mr-[2rpx]">¥</text>
|
|
||||||
<text class="text-[28rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(item.info.goodsSku)).toFixed(2)}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[70rpx] box-border text-right text-[#fff] pr-[8rpx] text-[22rpx] font-500 leading-[44rpx] rounded-tr-[20rpx] rounded-br-[20rpx] rounded-tl-[24rpx] relative" :style="{'background-color':item.button.color}">
|
|
||||||
<text>{{item.button.text}}</text>
|
|
||||||
<image class="w-[24rpx] h-[44rpx] absolute top-[-2rpx] left-0" :src="img('/addon/shop/Union.png')" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</x-skeleton>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 商品推荐
|
|
||||||
import { ref,reactive,computed, watch, onMounted, nextTick,getCurrentInstance } from 'vue';
|
|
||||||
import { redirect, img, deepClone } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { getGoodsComponents } from '@/addon/shop/api/goods';
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','value']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
const emits = defineEmits(['loadingFn']); //商品数据加载完成之后触发
|
|
||||||
|
|
||||||
const goodsNum = ref(0);
|
|
||||||
|
|
||||||
const skeleton = reactive({
|
|
||||||
type: '',
|
|
||||||
loading: false,
|
|
||||||
config: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if(props.value) {
|
|
||||||
return props.value;
|
|
||||||
}else if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const itemCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.elementBgColor) style += 'background-color:' + diyComponent.value.elementBgColor + ';';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
//listFrame样式
|
|
||||||
const listFrameStyle = (item:any)=>{
|
|
||||||
var style= '';
|
|
||||||
if(item.listFrame.startColor){
|
|
||||||
if(item.listFrame.startColor && item.listFrame.endColor) style = `background:linear-gradient( 110deg, ${item.listFrame.startColor} 0%, ${item.listFrame.endColor} 100%);`;
|
|
||||||
else style = 'background-color:' + item.listFrame.startColor + ';';
|
|
||||||
}
|
|
||||||
return style
|
|
||||||
}
|
|
||||||
//moreTitle样式
|
|
||||||
const moreTitleStyle = (item:any)=>{
|
|
||||||
var style= '';
|
|
||||||
if(item.moreTitle.startColor){
|
|
||||||
if(item.moreTitle.startColor && item.moreTitle.endColor) style = `background:linear-gradient( 0deg, ${item.moreTitle.startColor} 0%, ${item.moreTitle.endColor} 100%);`;
|
|
||||||
else style = 'background-color:' + item.moreTitle.startColor + ';';
|
|
||||||
}
|
|
||||||
return style
|
|
||||||
}
|
|
||||||
//商品样式
|
|
||||||
const itemStyle = ref('');
|
|
||||||
const setItemStyle = ()=>{
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// uni.createSelectorQuery().in(instance).select('#warpStyle-'+diyComponent.value.id).boundingClientRect((res:any) => {
|
|
||||||
// uni.createSelectorQuery().in(instance).select('#item0'+diyComponent.value.id).boundingClientRect((data:any) => {
|
|
||||||
// itemStyle.value = `margin-right:${(res.width - data.width*3)/2}px;`
|
|
||||||
// }).exec()
|
|
||||||
// }).exec()
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
// itemStyle.value= 'margin-right:19rpx;'
|
|
||||||
// #endif
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) itemStyle.value = 'width: calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 40rpx) / 3);'
|
|
||||||
else itemStyle.value = 'width: calc((100vw - 40rpx) / 3 );'
|
|
||||||
}
|
|
||||||
|
|
||||||
setItemStyle();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const getGoodsListFn = () => {
|
|
||||||
let data: any = {}
|
|
||||||
if(diyComponent.value.source == 'all') {
|
|
||||||
data.num = diyComponent.value.list.length;
|
|
||||||
}else if(diyComponent.value.source == 'custom') {
|
|
||||||
data.goods_ids = diyComponent.value.goods_ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGoodsComponents(data).then((res) => {
|
|
||||||
let goodsObj = res.data;
|
|
||||||
goodsNum.value = goodsObj.length || 0;
|
|
||||||
diyComponent.value.list.filter((el:any, index)=>{
|
|
||||||
el.info=deepClone(goodsObj[index])
|
|
||||||
});
|
|
||||||
goodsList.value = deepClone(diyComponent.value.list)
|
|
||||||
skeleton.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
)
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
nextTick(() => {
|
|
||||||
if(diyComponent.value && diyComponent.value.list){
|
|
||||||
goodsList.value = diyComponent.value.list.map((el:any)=>{
|
|
||||||
let obj = deepClone(el)
|
|
||||||
obj.info={
|
|
||||||
goods_cover_thumb_mid:'',
|
|
||||||
goodsSku:{
|
|
||||||
price:'10.00'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
})
|
|
||||||
goodsNum.value = 3;
|
|
||||||
setItemStyle()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
getGoodsListFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.info.goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss">
|
|
||||||
<view class="px-[30rpx] pt-[30rpx] box-border pb-[30rpx]" :class="{'!pb-[120rpx]':diyComponent.isShowAccount}">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view :style="navbarInnerStyle"></view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<view v-if="info" class="flex items-center">
|
|
||||||
<!-- 唤起获取微信 -->
|
|
||||||
<u-avatar :src="img(info.headimg)" :size="'110rpx'" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" @click="clickAvatar" />
|
|
||||||
<view class="ml-[20rpx] flex-1">
|
|
||||||
<view class="text-[#ffffff] flex items-baseline flex-wrap" :style="{ color : diyComponent.textColor }">
|
|
||||||
<view class="text-[32rpx] truncate max-w-[320rpx] font-500 leading-[38rpx]">{{ info.nickname }}</view>
|
|
||||||
<view class="text-[26rpx] font-400 leading-[28rpx] ml-[10rpx]" v-if="info.mobile">{{info.mobile.replace(info.mobile.substring(3,7), "****")}}</view>
|
|
||||||
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view v-else-if="!info.mobile" @click="bindMobileFn" class="text-[22rpx] ml-[10rpx] px-[6rpx] border-[1rpx] border-solid border-[#E3E4E9] rounded-[8rpx] h-[34rpx] flex-center" :style="diyComponent.textColor ? { boxShadow: '0 0 0 1rpx ' + diyComponent.textColor, border: 'none' } : {}">{{ t('bindMobile') }}</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<button v-else-if="!info.mobile" class="text-[22rpx] ml-[10rpx] bg-[#fff] px-[6rpx] border-[1rpx] border-solid border-[#E3E4E9] rounded-[8rpx] h-[37rpx] flex-center mr-0" :style="diyComponent.textColor ? { boxShadow: '0 0 0 1rpx ' + diyComponent.textColor, border: 'none' } : {}" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">{{t('bindMobile')}}</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="text-[#666] text-[24rpx] font-400 leading-[28rpx] mt-[14rpx]" :style="{ color : diyComponent.uidTextColor }">UID:{{ info.member_no }}</view>
|
|
||||||
</view>
|
|
||||||
<text @click="redirect({ url: '/app/pages/setting/index' })" class="nc-iconfont nc-icon-shezhiV6xx1 text-[38rpx] ml-[10rpx]" :style="{ color : diyComponent.textColor }"></text>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center">
|
|
||||||
<u-avatar :src="img('static/resource/images/default_headimg.png')" :size="'100rpx'" @click="toLogin" />
|
|
||||||
<view class="ml-[20rpx] flex-1" @click="toLogin">
|
|
||||||
<view class="text-[32rpx] font-500 leading-[38rpx]" :style="{ color : diyComponent.textColor }">
|
|
||||||
{{ t('login') }}/{{ t('register') }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view @click="redirect({ url: '/app/pages/setting/index' })">
|
|
||||||
<text class="nc-iconfont nc-icon-shezhiV6xx1 text-[38rpx] ml-[10rpx]" :style="{ color : diyComponent.textColor }"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex mt-[40rpx] items-center" v-if="diyComponent.isShowAccount">
|
|
||||||
<view class="text-center w-[33.333%] flex-shrink-0">
|
|
||||||
<view class="text-[36rpx] mb-[20rpx] font-500 price-font">
|
|
||||||
<view @click="redirect({url: '/app/pages/member/balance'})" :style="{ color : diyComponent.textColor }">{{ money }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[22rpx] font-400">
|
|
||||||
<view @click="redirect({url: '/app/pages/member/balance'})" :style="{ color : '#666' }">{{ t('balance') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-center w-[33.333%] flex-shrink-0">
|
|
||||||
<view class="text-[36rpx] mb-[20rpx] font-500 price-font">
|
|
||||||
<view @click="redirect({url: '/app/pages/member/point'})" :style="{ color : diyComponent.textColor }">{{ parseInt(info?.point) || 0 }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[22rpx] font-400">
|
|
||||||
<view @click="redirect({url: '/app/pages/member/point'})" :style="{ color : '#666' }">{{ t('point') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-center w-[33.333%] flex-shrink-0" @click="redirect({ url: '/addon/shop/pages/member/my_coupon' })">
|
|
||||||
<view class="text-[36rpx] mb-[20rpx] font-500 price-font">
|
|
||||||
<view :style="{ color : diyComponent.textColor }">{{ couponCount }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[22rpx] font-400">
|
|
||||||
<view :style="{ color : '#666' }">{{ t('coupon') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<information-filling ref="infoFillRef"></information-filling>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, ref, watch } from 'vue'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import { getMyCouponCount } from '@/addon/shop/api/coupon'
|
|
||||||
import { img, isWeixinBrowser, redirect, urlDeconstruction, moneyFormat } from '@/utils/common'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { wechatSync } from '@/app/api/system'
|
|
||||||
import useDiyStore from '@/app/stores/diy'
|
|
||||||
import useConfigStore from '@/stores/config'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','global']);
|
|
||||||
|
|
||||||
const configStore = useConfigStore()
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
if (diyComponent.value.bgUrl) {
|
|
||||||
style += 'background-image:url(' + img(diyComponent.value.bgUrl) + ');';
|
|
||||||
style += 'background-size: 100%;';
|
|
||||||
style += 'background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
const { query } = urlDeconstruction(location.href)
|
|
||||||
if (query.code && isWeixinBrowser()) {
|
|
||||||
setTimeout(() =>{
|
|
||||||
wechatSync({ code: query.code }).then(res => {
|
|
||||||
memberStore.getMemberInfo()
|
|
||||||
})
|
|
||||||
},1500)
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
const info = computed(() => {
|
|
||||||
// 装修模式
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return {
|
|
||||||
headimg: '',
|
|
||||||
nickname: '昵称',
|
|
||||||
member_level_name: '普通会员',
|
|
||||||
balance: 0,
|
|
||||||
point: 0,
|
|
||||||
money: 0,
|
|
||||||
mobile: '155****0549',
|
|
||||||
member_no: 'NIU0000021'
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getMyCouponCountFn()
|
|
||||||
return memberStore.info;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const money = computed(() => {
|
|
||||||
if (info.value) {
|
|
||||||
let m = parseFloat(info.value.balance) + parseFloat(info.value.money)
|
|
||||||
return moneyFormat(m.toString());
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const toLogin = () => {
|
|
||||||
let normalLogin = !configStore.login.is_username && !configStore.login.is_mobile && !configStore.login.is_bind_mobile; // 未开启普通登录
|
|
||||||
let authRegisterLogin = !configStore.login.is_auth_register; // 自动注册登录
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
if (isWeixinBrowser()) {
|
|
||||||
// 微信浏览器
|
|
||||||
if (normalLogin && authRegisterLogin) {
|
|
||||||
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
|
|
||||||
} else if (configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/member/index' })
|
|
||||||
} else if (normalLogin && configStore.login.is_auth_register) {
|
|
||||||
// 判断是否开启第三方自动注册登录
|
|
||||||
useLogin().getAuthCode({ scopes: 'snsapi_userinfo' })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 普通浏览器
|
|
||||||
if (normalLogin) {
|
|
||||||
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
|
|
||||||
} else if (configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/member/index' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP
|
|
||||||
if (normalLogin && authRegisterLogin) {
|
|
||||||
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
|
|
||||||
} else if (configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/member/index' })
|
|
||||||
} else if (normalLogin && configStore.login.is_auth_register) {
|
|
||||||
// 判断是否开启第三方自动注册登录
|
|
||||||
useLogin().getAuthCode()
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const infoFillRef:any = ref(false)
|
|
||||||
const clickAvatar = () => {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
infoFillRef.value.show = true
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
if (isWeixinBrowser()) {
|
|
||||||
useLogin().getAuthCode({ scopes: 'snsapi_userinfo' })
|
|
||||||
} else {
|
|
||||||
redirect({ url: '/app/pages/member/personal' })
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const couponCount = ref(0)
|
|
||||||
const getMyCouponCountFn= async()=>{
|
|
||||||
try {
|
|
||||||
const res = await getMyCouponCount({status:1})
|
|
||||||
couponCount.value = res.data
|
|
||||||
} catch (e){
|
|
||||||
couponCount.value = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const bindMobileFn = () =>{
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 导航栏内部盒子的样式
|
|
||||||
const navbarInnerStyle = computed(() => {
|
|
||||||
let style = '';
|
|
||||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
|
||||||
// #ifdef MP
|
|
||||||
if (props.global.topStatusBar.isShow == false) {
|
|
||||||
style += 'height:' + menuButtonInfo.height + 'px;';
|
|
||||||
style += 'padding-top:' + menuButtonInfo.top + 'px;';
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,476 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="shop-newcomer overflow-hidden" :style="warpCss" v-if="list && Object.keys(list).length">
|
|
||||||
<view class="style-1 p-[20rpx]" v-if="diyComponent.style.value == 'style-1'">
|
|
||||||
<view class="head flex justify-between items-center mb-[16rpx]" @click="toListFn()">
|
|
||||||
<image v-if="diyComponent.textImg" class="h-[34rpx] w-[auto]" :src="img(diyComponent.textImg)" mode="heightFix"></image>
|
|
||||||
<view class="time-wrap flex items-center ml-[auto]" v-show="timeData && Object.keys(timeData).length">
|
|
||||||
<text v-if="!getToken() && diyStore.mode != 'decorate'" class="text-[26rpx]" :style="{color: diyComponent.countDown.otherColor}">活动未开始</text>
|
|
||||||
<block v-else-if="activeState()">
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="mr-[10rpx] text-[24rpx]">距结束还有</text>
|
|
||||||
<up-count-down class="text-[#fff] text-[28rpx]" :time="newcomerTime" format="HH:mm:ss" @change="onChange">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="dayTransitionHours()">{{ dayTransitionHours() }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] ml-[6rpx] mr-[7rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.minutes">{{ timeData.minutes >= 10?timeData.minutes:'0'+timeData.minutes }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] ml-[6rpx] mr-[7rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.seconds">{{ timeData.seconds<10 ? '0'+timeData.seconds : timeData.seconds}}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-count-down>
|
|
||||||
</block>
|
|
||||||
<text v-else class="text-[28rpx]" :style="{color: diyComponent.countDown.otherColor}">活动已结束</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="content">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="inline-flex bg-[#fff] p-[16rpx] box-border" :style="commonTempCss()" @click="toDetail(list[0])">
|
|
||||||
<view class="w-[150rpx] h-[150rpx] flex items-center justify-center">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="150rpx" height="150rpx" :src="img(list[0].sku_image || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col ml-[20rpx] py-[4rpx] flex-1">
|
|
||||||
<view class="text-[26rpx] w-[200rpx] whitespace-pre-wrap leading-[1.4] multi-hidden" v-if="list[0].goods">{{list[0].goods.goods_name}}</view>
|
|
||||||
<view class="flex items-center justify-between mt-[auto]">
|
|
||||||
<view class="flex flex-1 items-center">
|
|
||||||
<text class="text-[20rpx] text-[#FF0000]">¥</text>
|
|
||||||
<text class="text-[28rpx] font-500 text-[#FF0000] max-w[120rpx] truncate">{{goodsPrice(list[0])}}</text>
|
|
||||||
</view>
|
|
||||||
<text class="italic flex items-center justify-center rounded-[40rpx] w-[60rpx] h-[40rpx] leading-1 text-[#fff] font-bold first-btn-bg">抢</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<block v-for="(item,index) in list" :key="index">
|
|
||||||
<view v-if="index > 0" class="ml-[10rpx] inline-flex flex-col items-center p-[16rpx] bg-[#fff] box-border" :style="commonTempCss()" @click="toDetail(item)">
|
|
||||||
<view class="w-[110rpx] h-[110rpx] flex items-center justify-center">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="110rpx" height="110rpx" :src="img(item.sku_image || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[110rpx] h-[110rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center mt-[auto]">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[24rpx] font-500 truncate">{{goodsPrice(item)}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<view class="style-2 p-[20rpx]" v-if="diyComponent.style.value == 'style-2'">
|
|
||||||
<view class="head flex justify-between items-center mb-[16rpx]" @click="toListFn()">
|
|
||||||
<image v-if="diyComponent.textImg" class="h-[34rpx] w-[auto]" :src="img(diyComponent.textImg)" mode="heightFix"></image>
|
|
||||||
<view class="time-wrap flex items-center ml-[auto]" v-show="timeData && Object.keys(timeData).length">
|
|
||||||
<text v-if="!getToken() && diyStore.mode != 'decorate'" class="text-[26rpx]" :style="{color: diyComponent.countDown.otherColor}">活动未开始</text>
|
|
||||||
<block v-else-if="activeState()">
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="mr-[10rpx] text-[24rpx]">倒计时</text>
|
|
||||||
<up-count-down class="text-[#fff] text-[28rpx]" :time="newcomerTime" format="DD:HH:mm" @change="onChange">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-if="timeData.days">{{ timeData.days }}</text>
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-else>0</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[22rpx] ml-[6rpx] mr-[7rpx]">天</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-if="timeData.hours">{{ timeData.hours>=10?timeData.hours:'0'+timeData.hours}}</text>
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[22rpx] ml-[6rpx] mr-[7rpx]">时</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-if="timeData.minutes">{{ timeData.minutes >= 10?timeData.minutes:'0'+timeData.minutes }}</text>
|
|
||||||
<text class="time-num" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[22rpx] ml-[6rpx] mr-[7rpx]">分</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-count-down>
|
|
||||||
</block>
|
|
||||||
<text v-else class="text-[28rpx]" :style="{color: diyComponent.countDown.otherColor}">活动已结束</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="content">
|
|
||||||
<view class="flex">
|
|
||||||
<view v-for="(item,index) in list" :key="index" class="item-bg mr-[10rpx] inline-flex flex-col items-center p-[6rpx] bg-[#fff] box-border" :style="commonTempCss()" @click="toDetail(item)">
|
|
||||||
<view class="flex items-center justify-center w-[146rpx] h-[146rpx]">
|
|
||||||
<u--image radius="var(--goods-rounded-small)" width="146rpx" height="146rpx" :src="img(item.sku_image || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[146rpx] h-[146rpx] rounded-[var(--goods-rounded-small)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<image class="h-[32rpx] w-[auto] mt-[12rpx] mb-[8rpx]" :src="img('addon/shop/diy/newcomer/style_2_img.png')" mode="heightFix"></image>
|
|
||||||
<view class="flex items-center text-[#fff] pb-[4rpx]">
|
|
||||||
<text class="text-[20rpx] font-500">¥</text>
|
|
||||||
<text class="text-[30rpx] max-w-[120rpx] font-500 truncate">{{goodsPrice(item)}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<view class="style-3 pt-[20rpx] pb-[10rpx] px-[10rpx]" v-if="diyComponent.style.value == 'style-3'">
|
|
||||||
<view class="head flex mx-[10rpx] items-center mb-[12rpx]" @click="toListFn()">
|
|
||||||
<image v-if="diyComponent.textImg" class="h-[34rpx] w-[auto] mr-[16rpx]" :src="img(diyComponent.textImg)" mode="heightFix"></image>
|
|
||||||
<view class="time-wrap flex items-center" v-show="timeData && Object.keys(timeData).length">
|
|
||||||
<text v-if="!getToken() && diyStore.mode != 'decorate'" :style="{color: diyComponent.countDown.otherColor}" class="text-[26rpx]">活动未开始</text>
|
|
||||||
<up-count-down v-else-if="activeState()" class="text-[#fff] text-[28rpx]" :time="newcomerTime" format="HH:mm:ss" @change="onChange">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="dayTransitionHours()">{{ dayTransitionHours() }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] font-bold ml-[6rpx] mr-[7rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.minutes">{{ timeData.minutes >= 10?timeData.minutes:'0'+timeData.minutes }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] font-bold ml-[6rpx] mr-[7rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.seconds">{{ timeData.seconds<10 ? '0'+timeData.seconds : timeData.seconds}}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-count-down>
|
|
||||||
<text v-else :style="{color: diyComponent.countDown.otherColor}" class="text-[26rpx]">活动已结束</text>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[auto] rounded-[20rpx] flex items-baseline pl-[16rpx] pr-[10rpx] pt-[10rpx] pb-[10rpx]" :style="subTitleCss" @click.stop="diyStore.toRedirect(diyComponent.subTitle.link)">
|
|
||||||
<text class="text-[22rpx]">{{diyComponent.subTitle.text}}</text>
|
|
||||||
<text class="iconfont iconarrow-right !text-[18rpx] font-bold"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="content bg-[#fff] box-border p-[16rpx] rounded-[var(--rounded-small)]">
|
|
||||||
<view class="flex">
|
|
||||||
<view v-for="(item,index) in list" :key="index" class="item-bg inline-flex flex-col items-center box-border" :class="{'mr-[16rpx]': index != (list.length-1)}" :style="commonTempCss()" @click="toDetail(item)">
|
|
||||||
<view class="bg-[#f8f8f8] flex items-center justify-center w-[152rpx] h-[152rpx]">
|
|
||||||
<u--image radius="var(--goods-rounded-small)" width="152rpx" height="152rpx" :src="img(item.sku_image || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[152rpx] h-[152rpx] rounded-[var(--goods-rounded-small)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<image class="h-[32rpx] w-[auto] mt-[12rpx] mb-[10rpx]" :src="img('addon/shop/diy/newcomer/style_3_img.png')" mode="heightFix"></image>
|
|
||||||
<view class="flex items-center text-[#FF0E00] pb-[2rpx]">
|
|
||||||
<text class="text-[20rpx] font-500">¥</text>
|
|
||||||
<text class="text-[30rpx] max-w-[120rpx] font-500 truncate">{{goodsPrice(item)}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<view class="style-4 p-[20rpx] pt-[24rpx]" v-if="diyComponent.style.value == 'style-4'" :style="{ background: 'url(' + img('addon/shop/diy/newcomer/style_4_head.png') + ') no-repeat'}">
|
|
||||||
<view class="head flex mx-[10rpx] items-center justify-between mb-[24rpx]">
|
|
||||||
<image v-if="diyComponent.textImg" class="h-[34rpx] w-[auto]" :src="img(diyComponent.textImg)" mode="heightFix"></image>
|
|
||||||
<view class="time-wrap ml-[auto] flex items-center -mt-[8rpx]" v-show="timeData && Object.keys(timeData).length">
|
|
||||||
<text v-if="!getToken() && diyStore.mode != 'decorate'" :style="{color: diyComponent.countDown.otherColor}" class="w-[200rpx] text-center text-[26rpx] pb-[4rpx]">活动未开始</text>
|
|
||||||
<block v-else-if="activeState()">
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="mr-[8rpx] text-[24rpx]">本场仅剩</text>
|
|
||||||
<up-count-down class="text-[#fff] text-[28rpx]" :time="newcomerTime" format="HH:mm:ss" @change="onChange">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="dayTransitionHours()">{{ dayTransitionHours() }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] ml-[4rpx] font-bold mr-[5rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.minutes">{{ timeData.minutes >= 10?timeData.minutes:'0'+timeData.minutes }}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
<text :style="{color: diyComponent.countDown.otherColor}" class="text-[20rpx] ml-[4rpx] font-bold mr-[5rpx]">:</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-if="timeData.seconds">{{ timeData.seconds<10 ? '0'+timeData.seconds : timeData.seconds}}</text>
|
|
||||||
<text class="time-num font-500" :style="countDownTextCss" v-else>00</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-count-down>
|
|
||||||
</block>
|
|
||||||
<text v-else :style="{color: diyComponent.countDown.otherColor}" class="w-[200rpx] text-center text-[24rpx] pb-[4rpx]">活动已结束</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-x="true" class="content">
|
|
||||||
<view class="flex">
|
|
||||||
<view v-for="(item,index) in list" :key="index" class="item-bg inline-flex flex-col items-center box-border" :class="{'mr-[20rpx]': index != (list.length-1)}" :style="commonTempCss()" @click="toDetail(item)">
|
|
||||||
<view class="relative flex items-center justify-center w-[100%] h-[130rpx] pt-[40rpx] mb-[10rpx]">
|
|
||||||
<u--image radius="var(--goods-rounded-small)" width="130rpx" height="130rpx" :src="img(item.sku_image || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[130rpx] h-[130rpx] rounded-[var(--goods-rounded-small)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="content-sign text-[20rpx] text-[#fff]">新人价</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[210rpx] relative -right-[2rpx] -bottom-[2rpx] flex items-center text-[#FF0E00] pb-[2rpx]">
|
|
||||||
<view class="flex items-center justify-center flex-1">
|
|
||||||
<text class="text-[20rpx] font-500">¥</text>
|
|
||||||
<text class="text-[36rpx] max-w-[140rpx] font-500 truncate">{{goodsPrice(item)}}</text>
|
|
||||||
</view>
|
|
||||||
<text class="btn-bg ml-auto">抢</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 新人专享
|
|
||||||
import { ref,reactive,computed, onMounted } from 'vue';
|
|
||||||
import { redirect, img, getToken } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { getNewcomersComponentsList } from '@/addon/shop/api/newcomer'
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','value']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if(props.value) {
|
|
||||||
return props.value;
|
|
||||||
}else if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/********* 倒计时 - start ***********/
|
|
||||||
// 使用 reactive 创建响应式对象
|
|
||||||
const timeData = ref({});
|
|
||||||
// 定义 onChange 方法
|
|
||||||
const onChange = (e) => {
|
|
||||||
timeData.value = e;
|
|
||||||
};
|
|
||||||
const newcomerTime: any = ref('');
|
|
||||||
/********* 倒计时 - end ***********/
|
|
||||||
|
|
||||||
const goodsPrice = (data: any)=> {
|
|
||||||
let price: any = 0;
|
|
||||||
if (data && data.newcomer_price) {
|
|
||||||
price = Number(data.newcomer_price).toFixed(2);
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将天转换成时
|
|
||||||
const dayTransitionHours = ()=>{
|
|
||||||
let num = timeData.value.days * 24 + timeData.value.hours;
|
|
||||||
num = num ? num : 0;
|
|
||||||
num = num >=10 ? num : '0' + num;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 活动状态
|
|
||||||
const activeState = ()=>{
|
|
||||||
let bool = true;
|
|
||||||
if(diyStore.mode != 'decorate' && timeData.value.days <= 0 && timeData.value.hours <= 0 && timeData.value.minutes <= 0 && timeData.value.seconds <= 0 && timeData.value.milliseconds <= 0){
|
|
||||||
bool = false;
|
|
||||||
}
|
|
||||||
return bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 倒计时样式
|
|
||||||
const countDownTextCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.countDown && diyComponent.value.countDown.numberBg) {
|
|
||||||
if (diyComponent.value.countDown.numberBg.startColor && diyComponent.value.countDown.numberBg.endColor) style += `background:linear-gradient(${diyComponent.value.countDown.numberBg.startColor},${diyComponent.value.countDown.numberBg.endColor});`;
|
|
||||||
else{
|
|
||||||
style += 'background-color:' + (diyComponent.value.countDown.numberBg.startColor || diyComponent.value.countDown.numberBg.endColor) + ';';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (diyComponent.value.countDown.numberColor) style += 'color:' + diyComponent.value.countDown.numberColor + ';';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// 公共模块颜色
|
|
||||||
const commonTempCss = ()=>{
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 副标题样式
|
|
||||||
const subTitleCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.subTitle) {
|
|
||||||
if (diyComponent.value.subTitle.startColor && diyComponent.value.subTitle.endColor) style += `background:linear-gradient(to right, ${diyComponent.value.subTitle.startColor},${diyComponent.value.subTitle.endColor});`;
|
|
||||||
else{
|
|
||||||
style += 'background-color:' + (diyComponent.value.subTitle.startColor || diyComponent.value.subTitle.endColor) + ';';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (diyComponent.value.subTitle.textColor) style += 'color:' + diyComponent.value.subTitle.textColor + ';';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const list: any = ref([])
|
|
||||||
const getNewcomerListFn = () => {
|
|
||||||
let data = {
|
|
||||||
limit: diyComponent.value.source == 'all' ? diyComponent.value.num : '',
|
|
||||||
sku_ids: diyComponent.value.source == 'custom' ? diyComponent.value.goods_ids : ''
|
|
||||||
}
|
|
||||||
getNewcomersComponentsList(data).then((res: any) => {
|
|
||||||
newcomerTime.value = res.data.validity_time;
|
|
||||||
let now = new Date();
|
|
||||||
let timestamp: any = now.getTime();
|
|
||||||
newcomerTime.value = Number(newcomerTime.value) * 1000 - timestamp;
|
|
||||||
|
|
||||||
list.value = res.data.goods_list
|
|
||||||
|
|
||||||
// 数据为空时隐藏整个组件
|
|
||||||
// if(!(list.value.length && (newcomerTime.value > 0 && isJoin.value == 0))) {
|
|
||||||
// diyComponent.value.pageStyle = '';
|
|
||||||
// }
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
let obj = {
|
|
||||||
goods: {
|
|
||||||
goods_name: "商品名称"
|
|
||||||
},
|
|
||||||
sku_image: "",
|
|
||||||
newcomer_price: 0.01
|
|
||||||
};
|
|
||||||
list.value.push(obj);
|
|
||||||
list.value.push(obj);
|
|
||||||
list.value.push(obj);
|
|
||||||
} else {
|
|
||||||
getNewcomerListFn();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 跳转专享列表
|
|
||||||
const toListFn = ()=>{
|
|
||||||
redirect({ url: '/addon/shop/pages/newcomer/list'})
|
|
||||||
}
|
|
||||||
// 跳转详情
|
|
||||||
const toDetail = (data: any)=> {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { sku_id: data.sku_id, type: 'newcomer_discount' } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.shop-newcomer{
|
|
||||||
.style-1{
|
|
||||||
.content{
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.first-btn-bg{
|
|
||||||
background: linear-gradient( 140deg, #FF9C24 0%, #FF4837 100%);
|
|
||||||
}
|
|
||||||
.time-num{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 42rpx;
|
|
||||||
padding: 0 6rpx;
|
|
||||||
height: 36rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.style-2{
|
|
||||||
.content{
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.item-bg{
|
|
||||||
background: linear-gradient( 140deg, #FF7A41, #FF2E0A);
|
|
||||||
}
|
|
||||||
.time-num{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 42rpx;
|
|
||||||
padding: 0 6rpx;
|
|
||||||
height: 36rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.style-3{
|
|
||||||
.content{
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.time-num{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 42rpx;
|
|
||||||
padding: 0 6rpx;
|
|
||||||
height: 36rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.style-4{
|
|
||||||
background-size: 100% 110rpx !important;
|
|
||||||
.content{
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.time-wrap{
|
|
||||||
margin-right: -14rpx;
|
|
||||||
.time-num{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 32rpx;
|
|
||||||
height: 36rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.item-bg{
|
|
||||||
background: linear-gradient(#FFFFFF 60%, #f7f7f7 100%);
|
|
||||||
}
|
|
||||||
.btn-bg{
|
|
||||||
background: linear-gradient( 140deg, #FE2B2B 0%, #FF7236 100%);
|
|
||||||
border-radius: 50%;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #fff;
|
|
||||||
width: 50rpx;
|
|
||||||
height: 50rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.content-sign{
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 20rpx;
|
|
||||||
z-index: 1;
|
|
||||||
background: linear-gradient( 140deg, #FE2B2B 0%, #FF7236 100%);
|
|
||||||
padding: 6rpx 8rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss">
|
|
||||||
<view class="diy-text relative">
|
|
||||||
<view class="px-[var(--pad-sidebar-m)] pt-[var(--pad-top-m)] pb-[40rpx] flex items-center justify-between">
|
|
||||||
<view @click="diyStore.toRedirect(diyComponent.link)">
|
|
||||||
<view class="max-w-[200rpx] truncate leading-[1] text-[30rpx]" :style="{ fontSize: diyComponent.fontSize * 2 + 'rpx', color: diyComponent.textColor, fontWeight: (diyComponent.fontWeight == 'normal' ? 500 : diyComponent.fontWeight) }">
|
|
||||||
{{ diyComponent.text }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view @click="redirect({ url: '/addon/shop/pages/order/list'})" class="flex items-center">
|
|
||||||
<text class="max-w-[200rpx] truncate text-[24rpx]" :style="{ color: diyComponent.more.color }">{{ diyComponent.more.text }}</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[24rpx]" :style="{ color: diyComponent.more.color }"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="pb-[var(--pad-top-m)] px-[var(--pad-sidebar-m)] flex items-center justify-between text-center">
|
|
||||||
<view class="flex flex-col items-center w-[20%] flex-shrink-0" @click="toList(1)">
|
|
||||||
<view class="relative w-[44rpx] h-[44rpx]">
|
|
||||||
<image class="w-[44rpx] h-[44rpx]" :src="img('addon/shop/diy/member/order1.png')" />
|
|
||||||
<view v-if="orderInfo.wait_pay"
|
|
||||||
:class="['absolute left-[35rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[30rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', orderInfo.wait_pay > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ orderInfo.wait_pay > 99 ? "99+" : orderInfo.wait_pay }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] leading-[1]" :style="{
|
|
||||||
fontSize: diyComponent.item.fontSize * 2 + 'rpx',
|
|
||||||
color: diyComponent.item.color,
|
|
||||||
fontWeight: diyComponent.item.fontWeight
|
|
||||||
}">待付款</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center w-[20%] flex-shrink-0" @click="toList(2)">
|
|
||||||
<view class="relative w-[44rpx] h-[44rpx]">
|
|
||||||
<image class="w-[44rpx] h-[44rpx]" :src="img('addon/shop/diy/member/order2.png')" />
|
|
||||||
<view v-if="orderInfo.wait_shipping"
|
|
||||||
:class="['absolute left-[35rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[30rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', orderInfo.wait_shipping > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ orderInfo.wait_shipping > 99 ? "99+" : orderInfo.wait_shipping }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] leading-[1]" :style="{
|
|
||||||
fontSize: diyComponent.item.fontSize * 2 + 'rpx',
|
|
||||||
color: diyComponent.item.color,
|
|
||||||
fontWeight: diyComponent.item.fontWeight
|
|
||||||
}">待发货</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center w-[20%] flex-shrink-0" @click="toList(3)">
|
|
||||||
<view class="relative w-[44rpx] h-[44rpx]">
|
|
||||||
<image class="w-[44rpx] h-[44rpx]" :src="img('addon/shop/diy/member/order3.png')" />
|
|
||||||
<view v-if="orderInfo.wait_take"
|
|
||||||
:class="['absolute left-[35rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[30rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', orderInfo.wait_take > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ orderInfo.wait_take > 99 ? "99+" : orderInfo.wait_take }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] leading-[1]" :style="{
|
|
||||||
fontSize: diyComponent.item.fontSize * 2 + 'rpx',
|
|
||||||
color: diyComponent.item.color,
|
|
||||||
fontWeight: diyComponent.item.fontWeight
|
|
||||||
}">待收货</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center w-[20%] flex-shrink-0" @click="toList(5)">
|
|
||||||
<view class="relative w-[44rpx] h-[44rpx]">
|
|
||||||
<image class="w-[44rpx] h-[44rpx]" :src="img('addon/shop/diy/member/order4.png')" />
|
|
||||||
<view v-if="orderInfo.evaluate"
|
|
||||||
:class="['absolute left-[35rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[30rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', orderInfo.evaluate > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ orderInfo.evaluate > 99 ? "99+" : orderInfo.evaluate }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] leading-[1]" :style="{
|
|
||||||
fontSize: diyComponent.item.fontSize * 2 + 'rpx',
|
|
||||||
color: diyComponent.item.color,
|
|
||||||
fontWeight: diyComponent.item.fontWeight
|
|
||||||
}">待评价</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center w-[20%] flex-shrink-0" @click="redirect({ url: '/addon/shop/pages/refund/list'})">
|
|
||||||
<view class="relative w-[44rpx] h-[44rpx]">
|
|
||||||
<image class="w-[44rpx] h-[44rpx]" :src="img('addon/shop/diy/member/order5.png')" />
|
|
||||||
<view v-if="orderInfo.refund"
|
|
||||||
:class="['absolute left-[35rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[30rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', orderInfo.refund > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ orderInfo.refund > 99 ? "99+" : orderInfo.refund }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] leading-[1]" :style="{
|
|
||||||
fontSize: diyComponent.item.fontSize * 2 + 'rpx',
|
|
||||||
color: diyComponent.item.color,
|
|
||||||
fontWeight: diyComponent.item.fontWeight
|
|
||||||
}">售后/退款</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, computed, watch,onMounted } from 'vue';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { img,redirect } from '@/utils/common';
|
|
||||||
import {getShopOrderNum} from '@/addon/shop/api/order';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},{deep: true})
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
orderInfo.value = {
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getShopOrderNumFn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const orderInfo = ref({})
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const getShopOrderNumFn=()=>{
|
|
||||||
getShopOrderNum().then((res:any)=>{
|
|
||||||
orderInfo.value = res.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const toList = (status:any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/list', param: { status } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss">
|
|
||||||
<view :style="maskLayer"></view>
|
|
||||||
<view class="diy-shop-search relative overflow-hidden flex items-center">
|
|
||||||
<image :src="img('addon/shop/diy/search_01.png')" class="w-[40rpx] h-[40rpx]" mode="widthFix" @click="toLink('/addon/shop/pages/goods/category')"></image>
|
|
||||||
<view class="flex-1 ml-[24rpx] rounded-[32rpx] flex items-center bg-[var(--temp-bg)] opacity-90 py-[10rpx] pl-[38rpx] pr-[32rpx] justify-between h-[60rpx] box-border" @click="toLink('/addon/shop/pages/goods/search')">
|
|
||||||
<text class="text-[var(--text-color-light9)] text-[26rpx]">{{ diyComponent.text }}</text>
|
|
||||||
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[24rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 搜索
|
|
||||||
import { ref,computed, watch, onMounted, nextTick,getCurrentInstance } from 'vue';
|
|
||||||
import { img, redirect } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += `background-image:url('${ img(diyComponent.value.componentBgUrl) }');`;
|
|
||||||
style += 'background-size: cover;background-repeat: no-repeat;';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 背景图加遮罩层
|
|
||||||
const maskLayer = computed(()=>{
|
|
||||||
var style = '';
|
|
||||||
if(diyComponent.value.componentBgUrl) {
|
|
||||||
style += 'position:absolute;top:0;width:100%;';
|
|
||||||
style += `background: rgba(0,0,0,${diyComponent.value.componentBgAlpha / 10});`;
|
|
||||||
style += `height:${height.value}px;`;
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if (newValue && newValue.componentName == 'ShopSearch') {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
const height = ref(0)
|
|
||||||
|
|
||||||
const refresh = ()=> {
|
|
||||||
nextTick(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.diy-shop-search').boundingClientRect((data: any) => {
|
|
||||||
height.value = data.height;
|
|
||||||
}).exec();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (url: any)=>{
|
|
||||||
if (diyStore.mode == 'decorate') return false;
|
|
||||||
redirect({ url })
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="warpCss" class="overflow-hidden" v-if="goodsList && goodsList[0]">
|
|
||||||
<view class="flex justify-between items-center mb-[20rpx]" v-if="diyComponent.textImg || diyComponent.subTitle.text">
|
|
||||||
<view class="h-[34rpx] flex items-center" v-if="diyComponent.textImg" @click="diyStore.toRedirect(diyComponent.textLink)">
|
|
||||||
<image class="h-[100%] w-[auto]" :src="img(diyComponent.textImg)" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center ml-[auto]" v-if="diyComponent.subTitle.text" @click="diyStore.toRedirect(diyComponent.subTitle.link)" :style="{'color': diyComponent.subTitle.textColor}">
|
|
||||||
<text class="text-[24rpx]">{{diyComponent.subTitle.text}}</text>
|
|
||||||
<text class="text-[22rpx] iconfont iconxiangyoujiantou"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="flex justify-between">
|
|
||||||
<!-- 轮播图 -->
|
|
||||||
<view class="relative w-[340rpx] overflow-hidden" :style="carouselCss">
|
|
||||||
<view v-if="diyComponent.list.length == 1" class="leading-0 overflow-hidden">
|
|
||||||
<view @click="diyStore.toRedirect(diyComponent.list[0].link)">
|
|
||||||
<image v-if="diyComponent.list[0].imageUrl" :src="img(diyComponent.list[0].imageUrl)" mode="heightFix" class="h-[504rpx] !w-full" :show-menu-by-longpress="true"/>
|
|
||||||
<image v-else :src="img('static/resource/images/diy/figure.png')" mode="heightFix" class="h-[504rpx] !w-full" :show-menu-by-longpress="true"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<block v-else>
|
|
||||||
<swiper class="swiper ns-indicator-dots-three h-[504rpx]" autoplay="true" circular="true" :indicator-dots="isShowDots" @change="swiperChange"
|
|
||||||
:indicator-color="diyComponent.indicatorColor" :indicator-active-color="diyComponent.indicatorActiveColor">
|
|
||||||
<swiper-item class="swiper-item" v-for="(item) in diyComponent.list" :key="item.id">
|
|
||||||
<view @click="diyStore.toRedirect(item.link)">
|
|
||||||
<view class="item h-[504rpx]">
|
|
||||||
<image v-if="item.imageUrl" :src="img(item.imageUrl)" mode="scaleToFill" class="w-full h-full" :show-menu-by-longpress="true"/>
|
|
||||||
<image v-else :src="img('static/resource/images/diy/figure.png')" mode="scaleToFill" class="w-full h-full" :show-menu-by-longpress="true"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</swiper-item>
|
|
||||||
</swiper>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view v-if="diyComponent.list.length > 1" class="swiper-dot-box straightLineStyle2">
|
|
||||||
<view v-for="(numItem, numIndex) in diyComponent.list" :key="numIndex" :class="['swiper-dot', { active: numIndex == swiperIndex }]" :style="[numIndex == swiperIndex ? { backgroundColor: diyComponent.indicatorActiveColor } : { backgroundColor: diyComponent.indicatorColor }]"></view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="w-[340rpx] h-[504rpx] flex flex-col bg-[#fff] box-border overflow-hidden" :style="goodsTempCss" @click="toLink(goodsList[0])">
|
|
||||||
<view :style="goodsImgCss" class="w-[346rpx] h-[350rpx] overflow-hidden">
|
|
||||||
<u--image width="346rpx" height="350rpx" :src="img(goodsList[0].goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[346rpx] h-[350rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="px-[16rpx] flex-1 pt-[16rpx] pb-[20rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#303133] leading-[40rpx] text-[28rpx] truncate" :style="{ color : diyComponent.goodsNameStyle.color, fontWeight : diyComponent.goodsNameStyle.fontWeight }">
|
|
||||||
{{goodsList[0].goods_name}}
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-baseline mt-[28rpx]" >
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font truncate max-w-[200rpx]" :style="{ color : diyComponent.priceStyle.mainColor }">
|
|
||||||
<text class="text-[24rpx] font-400">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(diyGoods.goodsPrice(goodsList[0])).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(diyGoods.goodsPrice(goodsList[0])).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(goodsList[0]) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="w-[44rpx] h-[44rpx] bg-[red] flex items-center justify-center rounded-[50%]" :style="{ backgroundColor : diyComponent.saleStyle.color }">
|
|
||||||
<text class="iconfont iconjia font-500 text-[32rpx] text-[#fff]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
// 精选推荐
|
|
||||||
import { ref,reactive,computed, watch, onMounted } from 'vue';
|
|
||||||
import { redirect, img } from '@/utils/common';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { getGoodsComponents } from '@/addon/shop/api/goods';
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','value']);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
|
|
||||||
const diyComponent = computed(() => {
|
|
||||||
if(props.value) {
|
|
||||||
return props.value;
|
|
||||||
}else if (diyStore.mode == 'decorate') {
|
|
||||||
return diyStore.value[props.index];
|
|
||||||
} else {
|
|
||||||
return props.component;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 轮播指示器
|
|
||||||
let isShowDots = ref(true)
|
|
||||||
// #ifdef H5
|
|
||||||
isShowDots.value = true;
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
isShowDots.value = false;
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
const warpCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
style += 'position:relative;';
|
|
||||||
if(diyComponent.value.componentStartBgColor) {
|
|
||||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
|
||||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsTempCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.elementBgColor) style += 'background-color:' + diyComponent.value.elementBgColor + ';';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-left-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-top-right-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomElementRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomElementRounded * 2 + 'rpx;';
|
|
||||||
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) style += 'width: calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 20rpx) / 2);'
|
|
||||||
else style += 'width: calc((100vw - 20rpx) / 2 );'
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsImgCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.topElementRounded) style += 'border-radius:' + diyComponent.value.topElementRounded * 2 + 'rpx;';
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
const carouselCss = computed(() => {
|
|
||||||
var style = '';
|
|
||||||
if (diyComponent.value.topCarouselRounded) style += 'border-top-left-radius:' + diyComponent.value.topCarouselRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.topCarouselRounded) style += 'border-top-right-radius:' + diyComponent.value.topCarouselRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomCarouselRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomCarouselRounded * 2 + 'rpx;';
|
|
||||||
if (diyComponent.value.bottomCarouselRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomCarouselRounded * 2 + 'rpx;';
|
|
||||||
|
|
||||||
if(diyComponent.value.margin && diyComponent.value.margin.both) style += 'width: calc((100vw - ' + (diyComponent.value.margin.both*4) + 'rpx - 20rpx) / 2);'
|
|
||||||
else style += 'width: calc((100vw - 20rpx) / 2 );'
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.pullDownRefreshCount,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
// 处理下拉刷新业务
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const getGoodsListFn = () => {
|
|
||||||
let data = {
|
|
||||||
num: 1,
|
|
||||||
goods_ids: diyComponent.value.source == 'custom' ? diyComponent.value.goods_ids : ''
|
|
||||||
}
|
|
||||||
getGoodsComponents(data).then((res) => {
|
|
||||||
goodsList.value = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refresh();
|
|
||||||
// 装修模式下刷新
|
|
||||||
if (diyStore.mode != 'decorate') {
|
|
||||||
watch(
|
|
||||||
() => diyComponent.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
{deep: true}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
// 装修模式下设置默认图
|
|
||||||
if (diyStore.mode == 'decorate') {
|
|
||||||
let obj = {
|
|
||||||
goods_cover_thumb_mid: "",
|
|
||||||
goods_name: "商品名称",
|
|
||||||
sale_num: "100",
|
|
||||||
unit: "件",
|
|
||||||
goodsSku:{price:100}
|
|
||||||
};
|
|
||||||
goodsList.value.push(obj);
|
|
||||||
}else{
|
|
||||||
getGoodsListFn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
const swiperIndex = ref(0);
|
|
||||||
const swiperChange = e => {
|
|
||||||
swiperIndex.value = e.detail.current;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.swiper.ns-indicator-dots-three :deep(.uni-swiper-dots-horizontal) {
|
|
||||||
bottom: 12rpx;
|
|
||||||
}
|
|
||||||
.swiper.ns-indicator-dots-three :deep(.uni-swiper-dot) {
|
|
||||||
width: 8rpx;
|
|
||||||
height: 8rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
margin-right: 14rpx;
|
|
||||||
}
|
|
||||||
.swiper.ns-indicator-dots-three :deep(.uni-swiper-dot):last-of-type {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
.swiper.ns-indicator-dots-three :deep(.uni-swiper-dot-active) {
|
|
||||||
width: 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-dot-box {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 4rpx;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 80rpx 8rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.swiper-dot {
|
|
||||||
background-color: #b2b2b2;
|
|
||||||
width: 10rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
height: 10rpx;
|
|
||||||
margin: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.straightLineStyle2{
|
|
||||||
.swiper-dot {
|
|
||||||
width: 8rpx;
|
|
||||||
height: 8rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
margin: 0;
|
|
||||||
margin-right: 14rpx;
|
|
||||||
&.last-of-type {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
&.active {
|
|
||||||
width: 30rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 满减 -->
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup class="manjian-popup" :show="manjianShow" @close="manjianShow = false" zIndex="999999">
|
|
||||||
<view class="min-h-[480rpx] popup-common" @touchmove.prevent.stop>
|
|
||||||
<view class="title !pb-[30rpx]">满减送</view>
|
|
||||||
<scroll-view class="h-[520rpx]" scroll-y="true">
|
|
||||||
<view class="px-[var(--popup-sidebar-m)] pt-[30rpx]">
|
|
||||||
<view v-for="(item,index) in data.content" :key="index" class="mb-[40rpx]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<text class="nc-iconfont nc-icon-qianbaoyueV6xx !text-[28rpx] mr-[10rpx]"></text>
|
|
||||||
<text class="text-[26rpx] font-500">{{item.limit}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx]">
|
|
||||||
<view v-if="item.goods && item.goods.length" class="flex mt-[20rpx]">
|
|
||||||
<view class="w-[100rpx] flex justify-end">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[22rpx] flex items-center justify-center px-[12rpx] h-[38rpx] mr-[6rpx]">赠品</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 ml-[8rpx]">
|
|
||||||
<view class="flex p-[20rpx] bg-[#f8f8f8] rounded-[var(--goods-rounded-big)] overflow-hidden" :class="{'mb-[20rpx]': goodsIndex != (item.goods.length-1)}" v-for="(goodsItem,goodsIndex) in item.goods" :key="goodsIndex" @click="goodsEvent(goodsItem.goods_id)">
|
|
||||||
<u--image radius="var(--goods-rounded-mid)" width="120rpx" height="120rpx" :src="img(goodsItem.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[120rpx] h-[120rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex flex-1 w-0 flex-col justify-between ml-[20rpx] pt-[6rpx] pb-[10rpx]">
|
|
||||||
<view class="truncate text-[#303133] text-[24rpx] leading-[32rpx]">
|
|
||||||
{{goodsItem.goods_name}}
|
|
||||||
</view>
|
|
||||||
<view class="flex items-baseline">
|
|
||||||
<view v-if="goodsItem.sku_name" class="truncate text-[22rpx] mt-[4rpx] text-[#999]">
|
|
||||||
{{ goodsItem.sku_name }}
|
|
||||||
</view>
|
|
||||||
<view class="font-400 ml-[auto] text-[24rpx] text-[#303133]">
|
|
||||||
<text>x</text>
|
|
||||||
<text>{{goodsItem.num}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<block v-if="item.give && item.give.length">
|
|
||||||
<view class="flex items-center mt-[24rpx]" v-for="(giveItem,giveIndex) in item.give" :key="giveIndex">
|
|
||||||
<view class="w-[100rpx] flex justify-end">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[22rpx] flex items-center justify-center px-[12rpx] h-[38rpx] mr-[6rpx]">{{giveItem.label}}</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-[24rpx]">{{giveItem.content}}</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<view class="flex items-baseline mt-[24rpx]" v-if="item.coupon && item.coupon.length">
|
|
||||||
<view class="w-[100rpx] flex justify-end">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[22rpx] flex items-center justify-center px-[12rpx] h-[38rpx] mr-[6rpx]">优惠券</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-wrap flex-1">
|
|
||||||
<text class="flex items-center text-[24rpx] leading-[1.3]" :class="{'mb-[16rpx]': couponIndex != (item.coupon.length-1)}" v-for="(couponItem,couponIndex) in item.coupon" :key="couponIndex">
|
|
||||||
{{couponItem.num}}张{{couponItem.coupon_name}}优惠券
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="manjianShow = false">确定</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { img, deepClone, getToken, redirect } from '@/utils/common'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
|
|
||||||
const manjianShow = ref(false);
|
|
||||||
const data = ref({});
|
|
||||||
const open = (parameter:any = {})=>{
|
|
||||||
data.value = cloneDeep(parameter);
|
|
||||||
data.value.content = [];
|
|
||||||
data.value.rule_json.forEach((item,index)=>{
|
|
||||||
if(item.is_show || item.is_show == undefined){
|
|
||||||
let obj = {};
|
|
||||||
obj.limit = `门槛满${data.value.condition_type == 'over_n_yuan' ? parseFloat(item.limit).toFixed(2) : item.limit }${data.value.condition_type == 'over_n_yuan' ? '元' : '件'}`;
|
|
||||||
if(item.is_give_goods){
|
|
||||||
obj.goods = deepClone(item.goods);
|
|
||||||
}
|
|
||||||
obj.give = [];
|
|
||||||
if(item.is_discount && item.discount_money){
|
|
||||||
obj.give.push({
|
|
||||||
label: '满减',
|
|
||||||
content: `订单金额${item.discount_type == 1 ? '减' : '打'}${item.discount_type == 1 ? parseFloat(item.discount_money).toFixed(2) : item.discount_money}${item.discount_type == 1 ? '元' : '折'}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if(item.is_free_shipping){
|
|
||||||
obj.give.push({
|
|
||||||
label: '包邮',
|
|
||||||
content: '商品包邮'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if(item.is_give_point && item.point){
|
|
||||||
obj.give.push({
|
|
||||||
label: '积分',
|
|
||||||
content: `送${item.point}积分`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if(item.is_give_balance && item.balance){
|
|
||||||
obj.give.push({
|
|
||||||
label: '余额',
|
|
||||||
content: `送${parseFloat(item.balance).toFixed(2)}余额`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if(item.is_give_coupon){obj.coupon = item.coupon;}
|
|
||||||
data.value.content.push(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
manjianShow.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsEvent = (id : number) => {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/goods/detail',
|
|
||||||
param: {
|
|
||||||
goods_id: id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
::v-deep .manjian-popup .u-slide-up-enter-to{
|
|
||||||
z-index: 999999 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="goods-recommend">
|
|
||||||
<view class="mt-[60rpx] flex flex-col items-center sidebar-margin pb-[30rpx]">
|
|
||||||
<view class="flex items-center mb-[30rpx]" v-if="goodsList && Object.keys(goodsList).length">
|
|
||||||
<image class="w-[38rpx] h-[22rpx]" :src="img('addon/shop_fenxiao/level/title_left.png')" mode="aspectFill"></image>
|
|
||||||
<text class="text-[30rpx] mx-[18rpx] font-500 text-[#EF000C]">猜你喜欢</text>
|
|
||||||
<image class="w-[38rpx] h-[22rpx]" :src="img('addon/shop_fenxiao/level/title_right.png')" mode="aspectFill"></image>
|
|
||||||
</view>
|
|
||||||
<diy-goods-list @loadingFn="getGoodsListFn" :component="goodsData"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { img } from '@/utils/common';
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import diyGoodsList from '@/addon/shop/components/diy/goods-list/index.vue';
|
|
||||||
// 获取分销商品数据
|
|
||||||
const goodsList = ref()
|
|
||||||
const getGoodsListFn = (data: any)=>{
|
|
||||||
goodsList.value = data || {}
|
|
||||||
}
|
|
||||||
// 商品列表组件
|
|
||||||
const goodsData = ref({
|
|
||||||
style: 'style-2',
|
|
||||||
num: 10,
|
|
||||||
source: 'all',
|
|
||||||
topElementRounded: 12,
|
|
||||||
bottomElementRounded: 12,
|
|
||||||
margin: {
|
|
||||||
both: 10,
|
|
||||||
bottom: 0,
|
|
||||||
top: 0
|
|
||||||
},
|
|
||||||
priceStyle: {
|
|
||||||
mainColor: "#ff4142",
|
|
||||||
control: true
|
|
||||||
},
|
|
||||||
goodsNameStyle:{
|
|
||||||
color: "#303133",
|
|
||||||
control: true,
|
|
||||||
fontWeight: "normal"
|
|
||||||
},
|
|
||||||
saleStyle: {
|
|
||||||
color: "#999",
|
|
||||||
control: true
|
|
||||||
},
|
|
||||||
labelStyle: {
|
|
||||||
isShow: true,
|
|
||||||
control: true
|
|
||||||
},
|
|
||||||
btnStyle: {
|
|
||||||
fontWeight:false,
|
|
||||||
padding: 0,
|
|
||||||
aroundRadius:25,
|
|
||||||
textColor: "#fff",
|
|
||||||
startBgColor: '#ff4142',
|
|
||||||
endBgColor: '#ff4142',
|
|
||||||
style: 'nc-icon-gouwuche1',
|
|
||||||
control: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,450 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-overlay :show="goodsSkuPop" @click="closeFn" zIndex="490">
|
|
||||||
<u-popup class="popup-type" :show="goodsSkuPop" @close="closeFn" mode="bottom" :overlay="false" zIndex="500">
|
|
||||||
<view class="py-[32rpx] relative" v-if="goodsDetail.detail" @touchmove.prevent.stop>
|
|
||||||
<view class="flex px-[32rpx]" :class="{'mb-[58rpx]':!(goodsDetail.is_newcomer && goodsDetail.newcomer_price != goodsDetail.price && (Object.keys(cartSkuList).length?parseInt(cartSkuList.num)+buyNum:buyNum)>1)}">
|
|
||||||
|
|
||||||
<view class="rounded-[var(--goods-rounded-big)] overflow-hidden w-[180rpx] h-[180rpx]">
|
|
||||||
<u--image width="180rpx" height="180rpx" :src="img(goodsDetail.detail.sku_image)" @click="imgListPreview(goodsDetail.detail.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[180rpx] h-[180rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-col justify-between ml-[24rpx] py-[10rpx]">
|
|
||||||
<view class="w-[100%]">
|
|
||||||
<view class="text-[var(--price-text-color)] flex items-baseline">
|
|
||||||
<text class="text-[32rpx] font-bold price-font">¥</text>
|
|
||||||
<text class="text-[48rpx] price-font">{{ parseFloat(goodsPrice).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[32rpx] mr-[6rpx] price-font">.{{ parseFloat(goodsPrice).toFixed(2).split('.')[1] }}</text>
|
|
||||||
<image class="h-[24rpx] ml-[6rpx] max-w-[60rpx]" v-if="priceType() == 'newcomer_price'" :src="img('addon/shop/newcomer.png')" mode="heightFix" />
|
|
||||||
<image class="h-[24rpx] ml-[6rpx] max-w-[44rpx]" v-if="priceType() == 'member_price'" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
<image class="h-[24rpx] ml-[6rpx] max-w-[72rpx]" v-if="priceType() == 'discount_price'" :src="img('addon/shop/discount.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[32rpx] text-[var(--text-color-light6)] mt-[12rpx]">库存{{goodsDetail.detail.stock}}{{ goodsDetail.goods.unit }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[30rpx] text-[var(--text-color-light6)] w-[100%] max-h-[60rpx] multi-hidden" v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length">已选规格:{{goodsDetail.detail.sku_spec_format}}</view>
|
|
||||||
<!-- <view v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length">
|
|
||||||
<text>已选规格:{{goodsDetail.detail.sku_spec_format}}</text>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center px-[32rpx] pt-[8rpx] pb-[16rpx] h-[58rpx] box-border" v-if="goodsDetail.is_newcomer && goodsDetail.newcomer_price != goodsDetail.price && (Object.keys(cartSkuList).length?parseInt(cartSkuList.num)+buyNum:buyNum)>1">
|
|
||||||
<image class="h-[24rpx] w-[56rpx]" :src="img('addon/shop/newcomer.png')" mode="aspectFit" />
|
|
||||||
<view class="text-[24rpx] text-[#FFB000] leading-[34rpx] ml-[8rpx]">第1{{goodsDetail.goods.unit}},¥{{parseFloat(goodsDetail.newcomer_price).toFixed(2)}}/{{goodsDetail.goods.unit}};第{{(parseInt(cartSkuList.num||0)+buyNum)>2?'2~'+(parseInt(cartSkuList.num||0)+buyNum):'2'}}{{goodsDetail.goods.unit}},¥{{parseFloat(parseFloat(goodsPrice)).toFixed(2)}}/{{goodsDetail.goods.unit}}</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view class="h-[500rpx] px-[32rpx] box-border mb-[60rpx]" scroll-y="true">
|
|
||||||
<view :class="{'mt-[20rpx]': 0 != index }" v-for="(item,index) in goodsDetail.goodsSpec" :key="index">
|
|
||||||
<view class="text-[28rpx] leading-[36rpx] mb-[24rpx]">{{item.spec_name}}</view>
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<view class="box-border bg-[var(--temp-bg)] text-[24rpx] px-[44rpx] text-center h-[56rpx] flex-center mr-[20rpx] mb-[20rpx] border-1 border-solid rounded-[50rpx] border-[var(--temp-bg)]"
|
|
||||||
:class="{'!border-[var(--primary-color)] text-[var(--primary-color)] !bg-[var(--primary-color-light)]': subItem.selected}"
|
|
||||||
v-for="(subItem,subIndex) in item.values" :key="subIndex" @click="change(subItem, index)">
|
|
||||||
{{subItem.name}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-center mt-[20rpx]">
|
|
||||||
<view class="text-[28rpx]">购买数量</view>
|
|
||||||
<text v-if="maxBuyShow > 0 && minBuyShow > 1" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">
|
|
||||||
({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售,限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})
|
|
||||||
</text>
|
|
||||||
<text v-else-if="maxBuyShow > 0" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">(限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})</text>
|
|
||||||
<text v-else-if="minBuyShow > 1" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售)</text>
|
|
||||||
|
|
||||||
<u-number-box :min="minBuy" :max="maxBuy" integer :step="1" input-width="68rpx" v-model="buyNum" input-height="52rpx">
|
|
||||||
<template #minus>
|
|
||||||
<view class="relative w-[30rpx] h-[30rpx]" @click="reduceNumChange">
|
|
||||||
<text class="text-[30rpx] nc-iconfont nc-icon-jianV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum <= minBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template #input>
|
|
||||||
<input class="text-[#303133] text-[28rpx] mx-[10rpx] w-[80rpx] h-[44rpx] bg-[var(--temp-bg)] leading-[44rpx] text-center rounded-[6rpx]" type="number" @input="goodsSkuInputFn" @blur="goodsSkuBlurFn" v-model="buyNum" />
|
|
||||||
</template>
|
|
||||||
<template #plus>
|
|
||||||
<view class="relative w-[30rpx] h-[30rpx]" @click="addNumChange">
|
|
||||||
<text class="text-[30rpx] nc-iconfont nc-icon-jiahaoV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum >= maxBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</u-number-box>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="px-[20rpx]">
|
|
||||||
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<button v-if="goodsDetail.detail.stock > 0" hover-class="none" class="!h-[80rpx] leading-[80rpx] text-[26rpx] font-500 rounded-[50rpx] primary-btn-bg" type="primary" @click="confirm">确定</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<template v-if="goodsDetail.detail.stock > 0">
|
|
||||||
<button v-if="isBindMobile && userInfo && !userInfo.mobile" hover-class="none" class="!h-[80rpx] leading-[80rpx] text-[26rpx] font-500 rounded-[50rpx] primary-btn-bg" type="primary" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">确定</button>
|
|
||||||
<button v-else hover-class="none" class="!h-[80rpx] leading-[80rpx] text-[26rpx] font-500 rounded-[50rpx] primary-btn-bg" type="primary" @click="confirm">确定</button>
|
|
||||||
</template>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<button hover-class="none" v-else class="!h-[80rpx] leading-[80rpx] text-[26rpx] font-500 text-[#fff] bg-[#ccc] rounded-[50rpx]">已售罄</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</u-overlay>
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, toRaw } from 'vue';
|
|
||||||
import { img, redirect, getToken } from '@/utils/common'
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
|
|
||||||
const props = defineProps(['goodsDetail']);
|
|
||||||
const goodsSkuPop = ref(false);
|
|
||||||
const callback:any = ref(null);
|
|
||||||
const currSpec = ref({
|
|
||||||
skuId: "",
|
|
||||||
name: []
|
|
||||||
})
|
|
||||||
const openType = ref("");
|
|
||||||
const buyNum = ref(1)
|
|
||||||
|
|
||||||
const maxBuy = ref(0); // 限购
|
|
||||||
const minBuy = ref(0); // 起售
|
|
||||||
const maxBuyShow = ref(0); // 限购
|
|
||||||
const minBuyShow = ref(0); // 起售
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = computed(() => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (Object.keys(goodsDetail.value).length && goodsDetail.value.type == 'newcomer_discount' && goodsDetail.value.is_newcomer && goodsDetail.value.newcomer_price != goodsDetail.value.price && (Object.keys(cartSkuList.value).length ? parseInt(cartSkuList.value.num) + buyNum.value : buyNum.value) < 2) {
|
|
||||||
// 新人价
|
|
||||||
price = goodsDetail.value.newcomer_price;
|
|
||||||
} else if (Object.keys(goodsDetail.value).length && goodsDetail.value.type == 'discount' && Object.keys(goodsDetail.value.goods).length && goodsDetail.value.goods.is_discount && goodsDetail.value.sale_price != goodsDetail.value.price) {
|
|
||||||
price = goodsDetail.value.sale_price // 折扣价
|
|
||||||
} else if (Object.keys(goodsDetail.value).length && Object.keys(goodsDetail.value.goods).length && goodsDetail.value.goods.member_discount && getToken() && goodsDetail.value.member_price != goodsDetail.value.price) {
|
|
||||||
price = goodsDetail.value.member_price // 会员价
|
|
||||||
} else {
|
|
||||||
price = goodsDetail.value.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 价格类型
|
|
||||||
const priceType = () => {
|
|
||||||
let type = "";
|
|
||||||
if (goodsDetail.value.type == 'newcomer_discount' && Object.keys(goodsDetail.value).length && goodsDetail.value.is_newcomer && goodsDetail.value.newcomer_price != goodsDetail.value.price && getToken()) {
|
|
||||||
type = 'newcomer_price'// 新人
|
|
||||||
} else if (goodsDetail.value.type == 'discount' && Object.keys(goodsDetail.value).length && Object.keys(goodsDetail.value.goods).length && goodsDetail.value.goods.is_discount && goodsDetail.value.sale_price != goodsDetail.value.price) {
|
|
||||||
type = 'discount_price'// 折扣
|
|
||||||
} else if (Object.keys(goodsDetail.value).length && Object.keys(goodsDetail.value.goods).length && goodsDetail.value.goods.member_discount && getToken() && goodsDetail.value.member_price != goodsDetail.value.price) {
|
|
||||||
type = 'member_price' // 会员价
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 会员信息
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
// 购物车数量
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
cartStore.getList();
|
|
||||||
const cartSkuList = computed(()=>{
|
|
||||||
if(goodsDetail.value && cartStore.cartList['goods_' + goodsDetail.value.goods_id] && cartStore.cartList['goods_' + goodsDetail.value.goods_id]['sku_' + goodsDetail.value.sku_id]) {
|
|
||||||
return cartStore.cartList['goods_' + goodsDetail.value.goods_id]['sku_' + goodsDetail.value.sku_id];
|
|
||||||
}else{
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const cartList = computed(() => cartStore.cartList)
|
|
||||||
const open = (type="",fn = "")=>{
|
|
||||||
openType.value = type;
|
|
||||||
goodsSkuPop.value = true;
|
|
||||||
callback.value = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsSkuInputFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= minBuy.value ){
|
|
||||||
buyNum.value = minBuy.value || 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= maxBuy.value){
|
|
||||||
buyNum.value = maxBuy.value;
|
|
||||||
}
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > goodsDetail.value.detail.stock){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
const goodsSkuBlurFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= minBuy.value ){
|
|
||||||
buyNum.value = minBuy.value || 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= maxBuy.value){
|
|
||||||
buyNum.value = maxBuy.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > goodsDetail.value.detail.stock){
|
|
||||||
buyNum.value = 0;
|
|
||||||
uni.showToast({
|
|
||||||
title: '商品库存小于起购数量',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeFn = ()=>{
|
|
||||||
goodsSkuPop.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsDetail = computed(() => {
|
|
||||||
let data = cloneDeep(props.goodsDetail);
|
|
||||||
|
|
||||||
// 重组数据结构
|
|
||||||
if(Object.keys(data).length){
|
|
||||||
|
|
||||||
if(!Object.keys(currSpec.value.name).length) currSpec.value.name = data.sku_spec_format.split(",");
|
|
||||||
|
|
||||||
data.goodsSpec.forEach((item: any,index: any)=>{
|
|
||||||
let specName = item.spec_values.split(",");
|
|
||||||
item.values = [];
|
|
||||||
specName.forEach((specItem: any, specIndex: any)=>{
|
|
||||||
item.values[specIndex] = {};
|
|
||||||
item.values[specIndex].name = specItem;
|
|
||||||
item.values[specIndex].selected = false;
|
|
||||||
item.values[specIndex].disabled = false;
|
|
||||||
|
|
||||||
// 选中规格
|
|
||||||
currSpec.value.name.forEach((currSpecItem, currSpecIndex)=>{
|
|
||||||
if(currSpecIndex == index && currSpecItem == specItem){
|
|
||||||
item.values[specIndex].selected = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
getSkuId();
|
|
||||||
|
|
||||||
// 当前详情内容
|
|
||||||
if(data.skuList && Object.keys(data.skuList).length){
|
|
||||||
data.skuList.forEach((idItem: any, idIndex: any)=>{
|
|
||||||
if(idItem.sku_id == currSpec.value.skuId){
|
|
||||||
data.detail = idItem;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(data.goods.is_limit){
|
|
||||||
if(data.goods.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(data.goods.limit_type == 1){ //单次限购
|
|
||||||
max_buy = data.goods.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = data.goods.max_buy - (data.goods.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
if(max_buy > data.detail.stock){
|
|
||||||
maxBuy.value = data.detail.stock
|
|
||||||
}else if(max_buy <= data.detail.stock){
|
|
||||||
maxBuy.value = max_buy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 限购开启且最大购买变为零时,初始值也应该是零
|
|
||||||
if(maxBuy.value == 0){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 仅用于展示
|
|
||||||
maxBuyShow.value = data.goods.max_buy; // 限购
|
|
||||||
}else{
|
|
||||||
maxBuy.value = data.detail.stock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起售
|
|
||||||
minBuy.value = data.goods.min_buy > 0 ? data.goods.min_buy : 1;
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > data.detail.stock){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}else{
|
|
||||||
buyNum.value = minBuy.value;
|
|
||||||
}
|
|
||||||
// 仅用于展示
|
|
||||||
minBuyShow.value = data.goods.min_buy;
|
|
||||||
return data;
|
|
||||||
})
|
|
||||||
|
|
||||||
const change = (data: any, index: any)=>{
|
|
||||||
currSpec.value.name[index] = data.name;
|
|
||||||
getSkuId(); // 刷新当前规格信息
|
|
||||||
}
|
|
||||||
|
|
||||||
const emits = defineEmits(['change'])
|
|
||||||
const getSkuId = ()=>{
|
|
||||||
props.goodsDetail.skuList.forEach((skuItem: any, skuIndex: any)=>{
|
|
||||||
if(skuItem.sku_spec_format == currSpec.value.name.toString()){
|
|
||||||
currSpec.value.skuId = skuItem.sku_id
|
|
||||||
emits('change',skuItem.sku_id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const addNumChange = () => {
|
|
||||||
if(minBuy.value && minBuy.value > goodsDetail.value.detail.stock){
|
|
||||||
uni.showToast({ title: '商品库存小于起购数量', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(goodsDetail.value.goods.is_limit){
|
|
||||||
let tips = `该商品单次限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
if(goodsDetail.value.goods.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
if(goodsDetail.value.goods.max_buy - maxBuy.value){
|
|
||||||
tips += `,已购${goodsDetail.value.goods.max_buy - maxBuy.value}件`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(buyNum.value >= maxBuy.value){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reduceNumChange = () => {
|
|
||||||
if(minBuy.value > 1){
|
|
||||||
let tips = `该商品起购${minBuy.value}件`;
|
|
||||||
if(buyNum.value <= minBuy.value){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const isBindMobile = ref(uni.getStorageSync('isbindmobile'))
|
|
||||||
|
|
||||||
//提交
|
|
||||||
const confirm = ()=> {
|
|
||||||
if(buyNum.value < 1) return;
|
|
||||||
|
|
||||||
// 检测是否登录
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({
|
|
||||||
url: '/addon/shop/pages/goods/detail',
|
|
||||||
param: {
|
|
||||||
sku_id: goodsDetail.value.sku_id,
|
|
||||||
type: goodsDetail.value.type
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
// 绑定手机号
|
|
||||||
if (uni.getStorageSync('isbindmobile')) {
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 加入购物车
|
|
||||||
if (openType.value == 'join_cart') {
|
|
||||||
let num = 0;
|
|
||||||
let limitNum = 0;
|
|
||||||
let cartId = "";
|
|
||||||
|
|
||||||
if (cartList.value['goods_' + goodsDetail.value.goods_id] && cartList.value['goods_' + goodsDetail.value.goods_id]['sku_' + goodsDetail.value.sku_id]) {
|
|
||||||
num = toRaw(cartList.value['goods_' + goodsDetail.value.goods_id]['sku_' + goodsDetail.value.sku_id].num);
|
|
||||||
cartId = toRaw(cartList.value['goods_' + goodsDetail.value.goods_id]['sku_' + goodsDetail.value.sku_id].id)
|
|
||||||
}
|
|
||||||
if (cartList.value['goods_' + goodsDetail.value.goods_id] && cartList.value['goods_' + goodsDetail.value.goods_id]) {
|
|
||||||
limitNum = toRaw(cartList.value['goods_' + goodsDetail.value.goods_id].totalNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
num += Number(buyNum.value);
|
|
||||||
limitNum += Number(buyNum.value);
|
|
||||||
/************** 限购-start **************/
|
|
||||||
if(goodsDetail.value.goods.is_limit){
|
|
||||||
let tips = `该商品单次限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
if(goodsDetail.value.goods.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
if(goodsDetail.value.goods.max_buy - maxBuy.value){
|
|
||||||
tips += `,已购${goodsDetail.value.goods.max_buy - maxBuy.value}件`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(limitNum > maxBuy.value){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/************** 限购-end **************/
|
|
||||||
cartStore.increase({
|
|
||||||
id: cartId || '',
|
|
||||||
goods_id: goodsDetail.value.goods_id,
|
|
||||||
sku_id: goodsDetail.value.sku_id,
|
|
||||||
stock: goodsDetail.value.stock,
|
|
||||||
sale_price: goodsDetail.value.sale_price,
|
|
||||||
num: num
|
|
||||||
}, 0, () => {
|
|
||||||
uni.showToast({
|
|
||||||
title: '加入购物车成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (openType.value == 'buy_now') {
|
|
||||||
// 立即购买
|
|
||||||
var data = {
|
|
||||||
sku_id: goodsDetail.value.sku_id,
|
|
||||||
num: buyNum.value
|
|
||||||
};
|
|
||||||
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'orderCreateData',
|
|
||||||
data: {
|
|
||||||
sku_data: [
|
|
||||||
data
|
|
||||||
],
|
|
||||||
extend_data: {
|
|
||||||
relate_id: '',
|
|
||||||
activity_type: goodsDetail.value.type // 目前营销活动有,新人价、限时折扣
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success: () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/payment' })
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
closeFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item: any) => {
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
::v-deep .u-number-box .u-number-box__slot{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import { redirect, img, getToken } from '@/utils/common';
|
|
||||||
export function useGoods(params: any = {}) {
|
|
||||||
|
|
||||||
const baseTagStyle = (data:any)=>{
|
|
||||||
let style = "";
|
|
||||||
if(data.color_json.text_color){
|
|
||||||
style += `color:${data.color_json.text_color};`;
|
|
||||||
}
|
|
||||||
if(data.color_json.border_color){
|
|
||||||
style += `border-color: ${data.color_json.border_color};`;
|
|
||||||
}
|
|
||||||
if(data.color_json.bg_color){
|
|
||||||
style += `background-color: ${data.color_json.bg_color};`;
|
|
||||||
}
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 价格类型
|
|
||||||
const priceType = (data:any) =>{
|
|
||||||
let type = "";
|
|
||||||
if(data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
type = 'member_price' // 会员价
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = (data:any) => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
price = data.goodsSku.member_price ? data.goodsSku.member_price : data.goodsSku.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = data.goodsSku ? data.goodsSku.price : data.price; //兼容商品推荐组件
|
|
||||||
}
|
|
||||||
return parseFloat(price);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 错误图片展示
|
|
||||||
const errorImgFn = (data: any, type: any) =>{
|
|
||||||
data[type] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
baseTagStyle: baseTagStyle,
|
|
||||||
goodsPrice: goodsPrice,
|
|
||||||
priceType: priceType,
|
|
||||||
error: errorImgFn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import { redirect, img, getToken } from '@/utils/common';
|
|
||||||
import { ref, reactive, computed, watch, onMounted, nextTick, getCurrentInstance } from 'vue';
|
|
||||||
|
|
||||||
/********************商品限购和商品起售********************/
|
|
||||||
export function useGoodsLimit() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取商品数量
|
|
||||||
* params 商品库存(stock),是否开启限购(is_limit),限购类型(limit_type),限购数量(max_buy),起购(min_buy),已购买数量(has_buy)
|
|
||||||
* return 商品数量,是否可以购买,原因
|
|
||||||
***/
|
|
||||||
const getGoodsNum = (params: any = {})=>{
|
|
||||||
let {stock,is_limit,limit_type,max_buy,min_buy,has_buy,num} = params;
|
|
||||||
|
|
||||||
let temp_range = {
|
|
||||||
'up':{ num: 0, tips: '', is_stock: false }, // 上限
|
|
||||||
'off':{ num: 0, tips: ''} // 下限
|
|
||||||
};
|
|
||||||
|
|
||||||
let returnObj = {
|
|
||||||
num: 0,
|
|
||||||
max_num: 0,
|
|
||||||
is_buy: true,
|
|
||||||
tips: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************* 起售-start ************************/
|
|
||||||
temp_range.off.num = min_buy > 0 ? min_buy : 1;
|
|
||||||
if(min_buy){
|
|
||||||
temp_range.off.tips = `该商品起购${params.min_buy}件`;
|
|
||||||
}
|
|
||||||
/******************* 起售-end ************************/
|
|
||||||
|
|
||||||
|
|
||||||
/******************* 限购-start ************************/
|
|
||||||
if(is_limit){
|
|
||||||
returnObj.is_buy = true;
|
|
||||||
if(max_buy){
|
|
||||||
if(limit_type == 1){ //单次限购
|
|
||||||
temp_range.up.num = max_buy;
|
|
||||||
temp_range.up.tips = `该商品单次限购${max_buy}件`;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = params.max_buy - (params.has_buy||0);
|
|
||||||
temp_range.up.num = buyVal > 0 ? buyVal : 0;
|
|
||||||
temp_range.up.tips = `该商品单次限购${max_buy}件`;
|
|
||||||
if(has_buy > 0){
|
|
||||||
temp_range.up.tips += `,已购${has_buy}件`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(temp_range.up.num > params.stock){
|
|
||||||
temp_range.up.num = params.stock;
|
|
||||||
temp_range.up.is_stock = true;
|
|
||||||
temp_range.up.tips = "商品库存不足";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
returnObj.is_buy = true;
|
|
||||||
temp_range.up.num = stock;
|
|
||||||
temp_range.up.tips = "商品库存不足";
|
|
||||||
}
|
|
||||||
/******************* 限购-end ************************/
|
|
||||||
if(temp_range.off.num > temp_range.up.num && temp_range.up.is_stock){
|
|
||||||
temp_range.up.tips = "商品库存不足";
|
|
||||||
}else if(temp_range.off.num > temp_range.up.num){
|
|
||||||
returnObj.num = temp_range.up.num;
|
|
||||||
}else{
|
|
||||||
if(num <= temp_range.off.num){
|
|
||||||
returnObj.tips = temp_range.off.tips;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getGoodsNum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"pages.goods.search": "搜索",
|
|
||||||
"pages.goods.cart": "购物车",
|
|
||||||
"pages.goods.collect": "商品收藏",
|
|
||||||
"pages.goods.browse": "我的足迹",
|
|
||||||
"pages.goods.category": "商品分类",
|
|
||||||
"pages.goods.detail": "商品详情",
|
|
||||||
"pages.goods.list": "商品列表",
|
|
||||||
"pages.goods.rank": "排行榜",
|
|
||||||
"pages.member.index": "个人中心",
|
|
||||||
"pages.member.my_coupon": "我的优惠券",
|
|
||||||
"pages.order.list": "订单列表",
|
|
||||||
"pages.order.detail": "订单详情",
|
|
||||||
"pages.order.payment": "待付款订单",
|
|
||||||
"pages.evaluate.order_evaluate": "商品评价",
|
|
||||||
"pages.evaluate.order_evaluate_view": "商品评价",
|
|
||||||
"pages.evaluate.list": "评价列表",
|
|
||||||
"pages.coupon.list": "优惠券列表",
|
|
||||||
"pages.coupon.detail": "优惠券详情",
|
|
||||||
"pages.discount.list": "限时折扣",
|
|
||||||
"pages.refund.list": "退款列表",
|
|
||||||
"pages.refund.detail": "退款详情",
|
|
||||||
"pages.refund.apply": "申请退款",
|
|
||||||
"pages.refund.edit_apply": "编辑退款信息",
|
|
||||||
"pages.refund.log": "协商记录",
|
|
||||||
"pages.point.index": "积分商城",
|
|
||||||
"pages.point.list": "积分商品列表",
|
|
||||||
"pages.point.detail": "积分商品详情",
|
|
||||||
"pages.point.payment": "待付款订单",
|
|
||||||
"pages.point.order_list": "积分兑换记录",
|
|
||||||
"pages.newcomer.list": "新人专享列表"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"orderNo": "订单号",
|
|
||||||
"actualPayment": "实付款",
|
|
||||||
"orderClose": "关闭订单",
|
|
||||||
"orderFinish": "确认收货",
|
|
||||||
"coupon":"优惠劵"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"all": "全部",
|
|
||||||
"price": "价格"
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"rankingRules":"榜单规则"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"coupon": "优惠券"
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"orderNo": "订单号",
|
|
||||||
"actualPayment": "实付款",
|
|
||||||
"orderClose": "关闭订单",
|
|
||||||
"orderFinish": "确认收货",
|
|
||||||
"topay": "去支付",
|
|
||||||
"orderDetail": "详情",
|
|
||||||
"orderTradeNo": "支付流水号",
|
|
||||||
"createTime": "创建时间",
|
|
||||||
"deliveryType": "配送方式",
|
|
||||||
"payTypeName": "支付方式",
|
|
||||||
"payTime": "支付时间",
|
|
||||||
"goodsMoney": "商品金额",
|
|
||||||
"deliveryMoney": "配送费用",
|
|
||||||
"orderMoney": "实付金额",
|
|
||||||
"evaluate": "评价",
|
|
||||||
"selectedEvaluate": "查看评价",
|
|
||||||
"index": "首页",
|
|
||||||
"discountMoney": "优惠金额",
|
|
||||||
"logisticsTracking":"查看物流",
|
|
||||||
"copy":"复制",
|
|
||||||
"detailedInformation":"详细信息",
|
|
||||||
"helpPay":"的帮付"
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"emptyAddress":"暂无收货地址,请先创建地址",
|
|
||||||
"addAddress":"新增收货地址",
|
|
||||||
"selectAddress":"选择地址",
|
|
||||||
"evaluate": "评价",
|
|
||||||
"money":"元",
|
|
||||||
"pendingPayment":"待支付",
|
|
||||||
"pendingPaymentTips":"剩余时间",
|
|
||||||
"service":"含物流运输服务",
|
|
||||||
"selectedEvaluate": "查看评价",
|
|
||||||
"orderClose": "关闭订单",
|
|
||||||
"orderFinish": "确认收货",
|
|
||||||
"topay": "支付",
|
|
||||||
"deliveryType":"配送方式",
|
|
||||||
"createTime":"下单时间"
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"orderNo": "订单号",
|
|
||||||
"actualPayment": "实付款",
|
|
||||||
"orderClose": "关闭订单",
|
|
||||||
"orderFinish": "确认收货",
|
|
||||||
"topay": "支付",
|
|
||||||
"orderDetail": "详情",
|
|
||||||
"evaluate": "评价",
|
|
||||||
"orderListempty":"暂无订单",
|
|
||||||
"emptyAddress":"暂无收货地址,请先创建地址"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"point":"积分",
|
|
||||||
"priceUnit":"元",
|
|
||||||
"redeemed":"已兑"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"orderNo": "订单号",
|
|
||||||
"actualPayment": "订单金额",
|
|
||||||
"orderClose": "关闭订单",
|
|
||||||
"orderFinish": "确认收货",
|
|
||||||
"topay": "支付",
|
|
||||||
"orderDetail": "详情",
|
|
||||||
"evaluate": "评价",
|
|
||||||
"selectedEvaluate": "查看评价",
|
|
||||||
"orderListempty": "暂无订单",
|
|
||||||
"deliveryType":"配送方式",
|
|
||||||
"money":"元",
|
|
||||||
"point": "积分"
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"refundDetail":"退货详情",
|
|
||||||
"fastRefundSuccessful":"极速退款成功",
|
|
||||||
"refundInfo":"由于你的信誉良好,已享受极速退款服务,退款即刻到账",
|
|
||||||
"refundType": "退款方式",
|
|
||||||
"refundMoney": "退款金额",
|
|
||||||
"refundCause": "退款原因",
|
|
||||||
"reasonRefusal": "拒绝原因",
|
|
||||||
"refundNo": "退款编号",
|
|
||||||
"createTime": "申请时间",
|
|
||||||
"createExplain": "退款说明",
|
|
||||||
"record": "协商记录",
|
|
||||||
"check": "查看",
|
|
||||||
"refundApply":"取消退款",
|
|
||||||
"cancelRefundContent": "撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请。",
|
|
||||||
"index": "首页"
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"refundMoney":"退款金额",
|
|
||||||
"refundApply":"取消退款",
|
|
||||||
"refund":"退款进度",
|
|
||||||
"cancelRefundContent": "撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请。"
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view v-if="Object.keys(detail).length&&!loading" class="overflow-hidden min-h-screen bg-style relative" :style="{ 'background': 'url(' + img('addon/shop/coupon/coupon_bg.png') + ') no-repeat' }">
|
|
||||||
<!-- #ifdef MP -->
|
|
||||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="relative mt-[236rpx] w-[100%] h-[932rpx]" :style="{ 'background': 'url(' + img('addon/shop/coupon/coupon_bg_02.png') + ') center / contain no-repeat' }">
|
|
||||||
<view v-if="detail.limit_count"
|
|
||||||
:style="{ 'background': 'url(' + img('addon/shop/coupon/top_tab.png') + ') center / cover no-repeat', 'transform': 'translateX(-50%)'}"
|
|
||||||
class="text-[32rpx] leading-[56rpx] top-[2rpx] left-[50%] px-[30rpx] box-border justify-center absolute min-w-[196rpx] h-[56rpx] flex items-center text-[#FFF9DD]">
|
|
||||||
限领{{ detail.limit_count }}张
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-center pt-[90rpx]">
|
|
||||||
<text class="max-w-[380rpx] text-[var(--price-text-color)] text-[140rpx] truncate price-font">{{ detail.coupon_price || 0.00 }}</text>
|
|
||||||
<text class="flex items-center justify-center text-[44rpx] mt-[54rpx] ml-[8rpx] text-[#F7D894] bg-[var(--price-text-color)] rounded-full w-[70rpx] h-[70rpx]">元</text>
|
|
||||||
</view>
|
|
||||||
<view class="h-[64rpx] leading-[64rpx] text-[42rpx] text-[#E22D17] mt-[10rpx] text-center">
|
|
||||||
<text v-if="detail.min_condition_money === '0.00'">无门槛</text>
|
|
||||||
<text v-else>满{{ detail.coupon_min_price }}元可用</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] h-[36rpx] text-[#E22D17] mt-[44rpx] text-center flex justify-center items-center">
|
|
||||||
<block v-if="detail.valid_type == 1">
|
|
||||||
<text>领取之日起</text>
|
|
||||||
<text>{{ detail.length}}</text>
|
|
||||||
<text>天内有效</text>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<text>有效期至</text>
|
|
||||||
<text>{{ detail.valid_end_time ? detail.valid_end_time.slice(0, 10) : '' }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-center items-center mt-[20rpx]">
|
|
||||||
<text v-if="detail.btnType === 'collected'"
|
|
||||||
class="!leading-[100rpx] text-center text-[rgba(255,255,255,1)] text-[46rpx] min-w-[240rpx] h-[106rpx]"
|
|
||||||
:style="{ 'background': 'url(' + img('addon/shop/coupon/coupon_btn_02.png') + ') center / contain no-repeat' }"
|
|
||||||
>已领完
|
|
||||||
</text>
|
|
||||||
<text v-if="detail.btnType === 'collecting'"
|
|
||||||
class="!leading-[100rpx] text-center text-[#E22D17] text-[46rpx] min-w-[240rpx] h-[106rpx]"
|
|
||||||
:style="{ 'background': 'url(' + img('addon/shop/coupon/coupon_btn.png') + ') center / contain no-repeat' }"
|
|
||||||
@click="collecting(detail.id)">领取
|
|
||||||
</text>
|
|
||||||
<text v-if="detail.btnType === 'using'"
|
|
||||||
class="!leading-[100rpx] text-center text-[#E22D17] text-[46rpx] min-w-[240rpx] h-[106rpx]"
|
|
||||||
:style="{ 'background': 'url(' + img('addon/shop/coupon/coupon_btn.png') + ') center / contain no-repeat' }"
|
|
||||||
@click="toLink(detail.id)">去使用
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[230rpx] h-[230rpx] box-border p-[15rpx] bg-[#fff] mx-[auto] mt-[50rpx]">
|
|
||||||
<image class="w-[200rpx] h-[200rpx]" :src="codeUrl" mode="aspectFill" />
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] text-[rgba(255,255,255,0.7)] mt-[30rpx] text-center">注:扫描二维码或点击右上角进行分享</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { img, redirect, handleOnloadParams, goback } from '@/utils/common'
|
|
||||||
import QRCode from "qrcode";
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import { getShopCouponInfo, getCoupon, getShopCouponQrocde } from '@/addon/shop/api/coupon'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const codeUrl = ref('')
|
|
||||||
const detail: any = ref({})
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let topTabbarData = topTabarObj.setTopTabbarParam({title:'优惠券详情'})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 处理小程序场景值参数
|
|
||||||
option = handleOnloadParams(option);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
if (!option.coupon_id) {
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/coupon/list',
|
|
||||||
title: '优惠券不存在'
|
|
||||||
};
|
|
||||||
goback(parameter)
|
|
||||||
} else {
|
|
||||||
getShopCouponInfoFn(option.coupon_id)
|
|
||||||
getShopCouponQrocdeFn(option.coupon_id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const getShopCouponInfoFn = (id: number) => {
|
|
||||||
loading.value = true
|
|
||||||
getShopCouponInfo(id).then((res: any) => {
|
|
||||||
detail.value = res.data
|
|
||||||
if (detail.value.sum_count != -1 && detail.value.receive_count === detail.value.sum_count) {
|
|
||||||
detail.value.btnType = 'collected'//已领完
|
|
||||||
}else if (!userInfo.value) {
|
|
||||||
detail.value.btnType = 'collecting'//领用
|
|
||||||
} else {
|
|
||||||
if (detail.value.is_receive && detail.value.limit_count === detail.value.member_receive_count) {
|
|
||||||
detail.value.btnType = 'using'//去使用
|
|
||||||
} else {
|
|
||||||
detail.value.btnType = 'collecting'//领用
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loading.value = false
|
|
||||||
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false
|
|
||||||
detail.value = {}
|
|
||||||
setTimeout(() => {
|
|
||||||
redirect({ url: '/addon/shop/pages/index', mode: 'reLaunch' })
|
|
||||||
}, 600)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getShopCouponQrocdeFn = (id: any) => {
|
|
||||||
// #ifdef H5
|
|
||||||
QRCode.toDataURL(window.location.href, { errorCorrectionLevel: 'L', margin: 0, width: 100 }).then(url => {
|
|
||||||
codeUrl.value = url
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
getShopCouponQrocde(id).then((res: any) => {
|
|
||||||
if (res.data) {
|
|
||||||
codeUrl.value = img(res.data);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const collecting = (coupon_id: any) => {
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/coupon/list' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
getCoupon({ coupon_id, number: 1 }).then(res => {
|
|
||||||
detail.value.btnType = 'using'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const toLink = (coupon_id: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/list', param: { coupon_id } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.border-color {
|
|
||||||
border-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-style {
|
|
||||||
background-size: 100% 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
box-shadow: 0 0 20px -1px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh] overflow-hidden" :style="themeColor()">
|
|
||||||
<view class="coupon-header fixed left-0 right-0 top-0 z-10080">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view :style="{height: headStyle, backgroundImage: 'url(' + img('addon/shop/coupon/coupon_uniapp.png') + ')',backgroundSize: '100%', backgroundPosition: 'bottom', backgroundRepeat: 'no-repeat'}">
|
|
||||||
<top-tabbar :data="param" class="top-header"/>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view class="h-[364rpx]" :style="{ backgroundImage: 'url(' + img('addon/shop/coupon/coupon_uniapp.png') + ')',backgroundSize: 'cover', backgroundPosition: 'bottom',backgroundRepeat: 'no-repeat'}"></view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="-mt-[-36rpx] px-[var(--sidebar-m)] py-[24rpx] flex items-center justify-between leading-[40rpx] text-[28rpx] bg-[var(--page-bg-color)] rounded-t-[26rpx] relative z-99999 !pl-[30rpx]" :class="{'!bg-[#fff]': typePopup}">
|
|
||||||
<text :class="{ 'text-primary font-500': searchType == 'all' }" @click="searchTypeFn('all')">默认排序</text>
|
|
||||||
<view class="flex items-center" :class="{ 'text-primary font-500': searchType == 'create_time' }" @click="searchTypeFn('create_time')">
|
|
||||||
<text class="mr-[4rpx]">最新</text>
|
|
||||||
<text v-if="create_time == 'asc'" class="text-[18rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangshangV6xx1" :class="{ '!text-primary': searchType == 'create_time' }"></text>
|
|
||||||
<text v-else class="text-[18rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangxiaV6xx1" :class="{ '!text-primary': searchType == 'create_time' }"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center" :class="{ 'text-primary font-500': searchType == 'price' }" @click="searchTypeFn('price')">
|
|
||||||
<text class="mr-[4rpx]">价格</text>
|
|
||||||
<text v-if="price == 'asc'" class="text-[18rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangshangV6xx1" :class="{ '!text-primary': searchType == 'price' }"></text>
|
|
||||||
<text v-else class="text-[18rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangxiaV6xx1" :class="{ '!text-primary': searchType == 'price' }"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center" :class="{'text-primary font-500': searchType == 'type' }" @click="searchTypeFn('type')">
|
|
||||||
<view class="w-[2rpx] h-[28rpx] bg-gradient-to-b from-[#333] to-[#fff] mr-[20rpx] flex-shrink-0"></view>
|
|
||||||
<text class="mr-[10rpx]">筛选</text>
|
|
||||||
<text class="nc-iconfont color-[var(--text-color-light6)] nc-icon-shaixuanV6xx text-[28rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" height="auto" @up="getShopCouponListFn" :top="mescrollTop">
|
|
||||||
<view v-if="list.length" class="pb-[var(--top-m)] sidebar-margin">
|
|
||||||
<template v-for="(item, index) in list">
|
|
||||||
<view v-if="item.btnType === 'collected'"
|
|
||||||
class="flex items-center relative w-[100%] rounded-[var(--rounded-big)] overflow-hidden bg-[#fff] py-[20rpx] background-size"
|
|
||||||
:class="{'mt-[var(--top-m)]':index}" :style="{ backgroundImage: 'url(' + img('addon/shop/coupon/coupn_loot.png') + ')'}" @click="toDetail(item.id)" >
|
|
||||||
<view class="box-border flex-1 border-0 border-r-[1px] border-[#FFDCDC] border-dashed flex items-center">
|
|
||||||
<view class="w-[164rpx] box-border flex justify-center ">
|
|
||||||
<view class="flex items-baseline text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[28rpx] leading-[34rpx] text-center font-400 price-font mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[54rpx] font-500 text-left leading-[70rpx] max-w-[136rpx] price-font">{{ item.coupon_price }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 box-border ml-[10rpx]">
|
|
||||||
<view class="text-[26rpx] leading-[42rpx] text-left font-500">
|
|
||||||
<text v-if="item.min_condition_money === '0.00'">无门槛</text>
|
|
||||||
<text v-else>满{{ item.coupon_min_price }}元可用</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx] text-left flex items-center">
|
|
||||||
<text class="w-[80rpx] text-center bg-[#FFEFF0] whitespace-nowrap text-[var(--primary-color)] text-[18rpx] h-[30rpx] leading-[30rpx] rounded-[16rpx] mr-[10rpx] flex-shrink-0">{{ item.type_name }}</text>
|
|
||||||
<text class="text-[24rpx] truncate max-w-[190rpx] leading-[30rpx] text-[var(--text-color-light6)]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[100%] mt-[10rpx] text-[20rpx] leading-[30rpx] text-[var(--text-color-light6)]">
|
|
||||||
<text v-if="item.valid_type == 1">领取之日起{{ item.length || '' }}天内有效</text>
|
|
||||||
<text v-else> 有效期至{{ item.valid_end_time ? item.valid_end_time.slice(0, 10) : '' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="pr-[20rpx] pl-[34rpx]">
|
|
||||||
<button class="flex-center" :style="{width:'150rpx',height:'60rpx',color:'#fff', fontSize:'24rpx', padding:'0',backgroundColor:'#FFB4B1', border:'none' ,opacity :'1',borderRadius:'30rpx'}" disabled>已领完</button>
|
|
||||||
</view>
|
|
||||||
<view class="absolute top-0 right-[190rpx] h-[10rpx] w-[20rpx] rounded-br-[20rpx] rounded-bl-[20rpx] bg-[var(--page-bg-color)] "></view>
|
|
||||||
<view class="absolute bottom-0 right-[190rpx] h-[10rpx] w-[20rpx] rounded-tr-[20rpx] rounded-tl-[20rpx] bg-[var(--page-bg-color)]"></view>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center relative w-[100%] rounded-[var(--rounded-big)] overflow-hidden bg-[#fff] py-[20rpx] background-size" :class="{'mt-[var(--top-m)]':index}" @click="toDetail(item.id)">
|
|
||||||
<view class="relative box-border flex-1 border-0 border-r-[1px] border-[#FFDCDC] border-dashed flex items-center pl-[10rpx]">
|
|
||||||
<view class="w-[164rpx] box-border flex justify-center">
|
|
||||||
<view class="flex items-baseline text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[28rpx] leading-[34rpx] text-center font-400 price-font mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[54rpx] font-500 text-left leading-[70rpx] max-w-[136rpx] price-font">{{ item.coupon_price }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 box-border ml-[10rpx]">
|
|
||||||
<view class="text-[26rpx] leading-[42rpx] text-left font-500">
|
|
||||||
<text v-if="item.min_condition_money === '0.00'">无门槛</text>
|
|
||||||
<text v-else>满{{ item.coupon_min_price }}元可用</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx] text-left flex items-center">
|
|
||||||
<text class="w-[80rpx] bg-[#FFEFF0] whitespace-nowrap text-[var(--primary-color)] text-[18rpx] h-[30rpx] leading-[30rpx] text-center rounded-[16rpx] mr-[10rpx] flex-shrink-0">{{ item.type_name }}</text>
|
|
||||||
<text class="text-[24rpx] truncate max-w-[190rpx] leading-[30rpx] text-[var(--text-color-light9)]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[100%] mt-[6rpx] text-[20rpx] leading-[30rpx] text-[var(--text-color-light9)]">
|
|
||||||
<text v-if="item.valid_type == 1">领取之日起<text>{{ item.length || '' }}</text>天内有效</text>
|
|
||||||
<text v-else> 有效期至<text>{{ item.valid_end_time ? item.valid_end_time.slice(0, 10) : '' }}</text></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.btnType === 'collecting'" @click.stop="collecting(item.id, index)" class="pr-[20rpx] pl-[34rpx]">
|
|
||||||
<button class="flex-center" :style="{width:'150rpx',height:'60rpx',color:'#fff', fontSize:'24rpx', padding:'0', backgroundColor:'var(--primary-color)',border:'none',borderRadius:'30rpx'}">立即领取</button>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.btnType === 'using'" @click.stop="toLink(item.id)" class="pr-[20rpx] pl-[34rpx]">
|
|
||||||
<button class="flex-center" :style="{width:'150rpx',height:'60rpx',color:'var(--primary-color)', fontSize:'24rpx', padding:'0',backgroundColor:'transparent',border:'2rpx solid var(--primary-color)',borderRadius:'30rpx'}">去使用</button>
|
|
||||||
</view>
|
|
||||||
<view class="absolute top-0 right-[190rpx] h-[10rpx] w-[20rpx] rounded-br-[20rpx] rounded-bl-[20rpx] bg-[var(--page-bg-color)] "></view>
|
|
||||||
<view class="absolute bottom-0 right-[190rpx] h-[10rpx] w-[20rpx] rounded-tr-[20rpx] rounded-tl-[20rpx] bg-[var(--page-bg-color)]"></view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<!-- <view :style="{'height': nullPageHeight}" class="noData bg-[#fff] rounded-[var(--rounded-big)] flex items-center justify-center"> -->
|
|
||||||
<!-- </view> -->
|
|
||||||
</view>
|
|
||||||
<!-- <view class=""> -->
|
|
||||||
<mescroll-empty v-if="!list.length && !loading" :option="{tip : '暂无优惠券',btnText:'去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/goods/list' })"></mescroll-empty>
|
|
||||||
<!-- </view> -->
|
|
||||||
</mescroll-body>
|
|
||||||
|
|
||||||
<u-popup :show="typePopup" mode="top" @close="typePopup = false" :customStyle="{top:typePopupTopVal}" :safeAreaInsetBottom="false">
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="'id' + (subActive ? subActive - 1 : 0)" class="px-[var(--sidebar-m)] box-border bg-white rounded-b-[26rpx]">
|
|
||||||
<view class="items-center flex py-[20rpx] border-0 border-t-[2rpx] border-solid border-[#F0F2F8]">
|
|
||||||
<text class="flex-shrink-0 w-[120rpx] h-[50rpx] text-[24rpx] leading-[50rpx] text-center text-[#333] bg-[var(--temp-bg)] rounded-[30rpx] border-box mr-[20rpx] border-[2rpx] border-solid border-[#F8F9FD]" :class="{'!text-primary !border-primary !bg-[rgba(239,0,12,0.04)] font-500':item.value == curType}"
|
|
||||||
v-for="(item,index) in typeList" :key="index" :id="'id' + index"
|
|
||||||
@click="typeClick(index,item.value)">{{item.label}}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, nextTick, getCurrentInstance } from 'vue'
|
|
||||||
import { img, redirect, pxToRpx } from '@/utils/common'
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import { getShopCouponList, getCoupon, getMyCouponType } from '@/addon/shop/api/coupon'
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
|
|
||||||
import {onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
|
|
||||||
// 获取系统状态栏的高度
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let param = topTabarObj.setTopTabbarParam({title:'优惠券列表'})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
// 头部图片的高度
|
|
||||||
const headStyle = computed(() => {
|
|
||||||
let style = (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + pxToRpx(8) + 364) + 'rpx'
|
|
||||||
return style
|
|
||||||
})
|
|
||||||
|
|
||||||
const mescrollTop = computed(() => {
|
|
||||||
let style = Object.keys(menuButtonInfo).length ? (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + pxToRpx(8) + 416) + 'rpx' : '416rpx'
|
|
||||||
return style
|
|
||||||
})
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
let typePopupTopVal = ref()
|
|
||||||
const typePopupTopFn = () => {
|
|
||||||
nextTick(() => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.coupon-header').boundingClientRect((data:any) => {
|
|
||||||
typePopupTopVal.value = data.height + 'px';
|
|
||||||
}).exec();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
typePopupTopFn();
|
|
||||||
|
|
||||||
// // 获取空页面高度
|
|
||||||
// const nullPageHeight = computed(() => {
|
|
||||||
// let hei = '';
|
|
||||||
// // #ifndef H5
|
|
||||||
// // 屏幕高度 - 图片高度 - 上下padding + 内容框上移高度 - 苹果手机安全距离
|
|
||||||
// hei = `calc(100vh - ${mescrollTop.value} - 40rpx)`
|
|
||||||
// // #endif
|
|
||||||
// // #ifdef H5
|
|
||||||
// // 屏幕高度 - 图片高度 - 上下padding + 内容框上移高度 - 苹果手机安全距离
|
|
||||||
// hei = `calc(100vh - 416rpx)`
|
|
||||||
// // #endif
|
|
||||||
// return hei
|
|
||||||
// })
|
|
||||||
|
|
||||||
const list: any = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
const getShopCouponListFn = (mescroll: any) => {
|
|
||||||
loading.value = true;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
order: searchType.value === 'all' ? '' : searchType.value,
|
|
||||||
sort: searchType.value == 'price' ? price.value : create_time.value,
|
|
||||||
type: curType.value || ''
|
|
||||||
};
|
|
||||||
|
|
||||||
getShopCouponList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>).map((el: any) => {
|
|
||||||
if (el.sum_count != -1 && el.receive_count === el.sum_count) {
|
|
||||||
el.btnType = 'collected'//已领完
|
|
||||||
}else if (!userInfo.value) {
|
|
||||||
el.btnType = 'collecting'//领用
|
|
||||||
} else {
|
|
||||||
if (el.is_receive && el.limit_count === el.member_receive_count) {
|
|
||||||
el.btnType = 'using'//去使用
|
|
||||||
} else {
|
|
||||||
el.btnType = 'collecting'//领用
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return el
|
|
||||||
})
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const collecting = (coupon_id: any, index: number) => {
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/coupon/list' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
getCoupon({ coupon_id, number: 1, type: 'receive' }).then((res: any) => {
|
|
||||||
if (res.code > 0) {
|
|
||||||
list.value[index].member_receive_count += 1
|
|
||||||
list.value[index].receive_count += 1
|
|
||||||
if (list.value[index].member_receive_count == list.value[index].limit_count
|
|
||||||
|| (list.value[index].sum_count != -1 && list.value[index].receive_count === list.value[index].sum_count)
|
|
||||||
) {
|
|
||||||
list.value[index].btnType = 'using'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toDetail = (coupon_id: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/coupon/detail', param: { coupon_id } })
|
|
||||||
}
|
|
||||||
const toLink = (coupon_id: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/list', param: { coupon_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优惠劵
|
|
||||||
const price = ref('');
|
|
||||||
const create_time = ref('');
|
|
||||||
const searchType = ref('all');
|
|
||||||
// 类型
|
|
||||||
const subActive = ref<number>(0)
|
|
||||||
const curType = ref('')
|
|
||||||
const typeList = ref<Array<Object>>([])
|
|
||||||
const typePopup = ref<boolean>(false)
|
|
||||||
const getMyCouponTypeFn = () =>{
|
|
||||||
getMyCouponType().then((res: any) =>{
|
|
||||||
const obj = { label: '全部', value: '' };
|
|
||||||
typeList.value.push(obj)
|
|
||||||
typeList.value = typeList.value.concat(res.data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onLoad(()=>{
|
|
||||||
getMyCouponTypeFn()
|
|
||||||
})
|
|
||||||
|
|
||||||
const typeClick = (index : number,data:any) =>{
|
|
||||||
subActive.value = index
|
|
||||||
curType.value = data
|
|
||||||
list.value = []
|
|
||||||
getMescroll().resetUpScroll()
|
|
||||||
typePopup.value = false
|
|
||||||
}
|
|
||||||
// 筛选
|
|
||||||
const searchTypeFn = (type: any) => {
|
|
||||||
searchType.value = type;
|
|
||||||
if ( type == 'all') {
|
|
||||||
create_time.value = '';
|
|
||||||
price.value = '';
|
|
||||||
}
|
|
||||||
if ( type == 'price') {
|
|
||||||
create_time.value = '';
|
|
||||||
if(price.value){
|
|
||||||
price.value = price.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
}else{
|
|
||||||
price.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( type == 'create_time') {
|
|
||||||
price.value = '';
|
|
||||||
if(create_time.value){
|
|
||||||
create_time.value = create_time.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
}else{
|
|
||||||
create_time.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == 'type') {
|
|
||||||
create_time.value = 'asc';
|
|
||||||
price.value = 'asc';
|
|
||||||
typePopup.value = true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
typePopup.value = false;
|
|
||||||
list.value = [];
|
|
||||||
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
button{
|
|
||||||
box-sizing: border-box;
|
|
||||||
&::after {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.background-size{
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right top;
|
|
||||||
background-size: 27%;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-popup .u-popup__content){
|
|
||||||
border-bottom-left-radius:26rpx;
|
|
||||||
border-bottom-right-radius:26rpx;
|
|
||||||
}
|
|
||||||
:deep(.mescroll-empty){
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="discount bg-[var(--page-bg-color)] min-h-[100vh]" :style="themeColor()">
|
|
||||||
<view class="fixed top-0 left-0 w-full z-10 text-[0]">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view class="absolute top-0 left-0 right-0 z-999">
|
|
||||||
<top-tabbar :data="param" class="top-header"/>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<u-swiper v-if="bannerList.length" :list="imgList" :indicator="bannerList.length" :indicatorStyle="{'bottom': '60rpx',}" :autoplay="true" :height="headStyle" @click="toRedirect"></u-swiper>
|
|
||||||
<image v-if="!bannerListLoading&&!bannerList.length" :src="img('addon/shop/discount/discount_banner.png')" mode="scaleToFill" class="w-full" :style="{height: headStyle}" :show-menu-by-longpress="true"/>
|
|
||||||
<view class="relative w-full h-[110rpx] mt-[-40rpx] z-5" v-if="discountList.length">
|
|
||||||
<view class="bg-[#f24f3d] w-[750rpx] rounded-tl-[24rpx] rounded-tr-[24rpx] h-[96rpx] absolute left-0 bottom-[1rpx]"></view>
|
|
||||||
<scroll-view :scroll-x="true" class="h-[110rpx] absolute left-0 bottom-0 z-5">
|
|
||||||
<view class="flex items-end h-[100%]" :style="{'width':187.5*discountList.length+'rpx'}" >
|
|
||||||
<view class="w-[187.5rpx] h-[100rpx] relative flex-shrink-0" v-for="(item,index) in discountList" @click="navClick(item)">
|
|
||||||
<view class="w-full absolute left-0 top-0 z-10 text-[#fff] text-center pt-[14rpx]">
|
|
||||||
<view class="text-[28rpx] leading-[39rpx] font-500 px-[10rpx] h-[39rpx] overflow-hidden" :class="{'!text-[#333]':active==item.active_id}">{{item.active_desc}}</view>
|
|
||||||
<view class="flex justify-center w-full">
|
|
||||||
<text class="text-[22rpx] h-[36rpx] flex-center mt-[5rpx]" :class="{'active flex items-center justify-center':active==item.active_id}">{{item.active_status=='not_active'?'预告':item.active_status_name}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<template v-if="active==item.active_id">
|
|
||||||
<image v-if="discountList.length<4" class="absolute bottom-0 z-5 h-[110rpx] z-5" :class="{'left-0 w-[230rpx]':index==0,'left-[-41.25rpx] w-[270rpx]':index!=0}" :src="img(index==0?'addon/shop/discount/nav-left.png':'addon/shop/discount/nav-center.png')" />
|
|
||||||
<image v-if="discountList.length>=4" class="absolute bottom-0 z-5 h-[110rpx] z-5" :class="{'left-0 w-[230rpx]':index==0,'left-[-41.25rpx] w-[270rpx]':index!=0&&index!=discountList.length-1 ,'right-0 w-[230rpx]':index==discountList.length-1}" :src="img(index==0?'addon/shop/discount/nav-left.png':index==discountList.length-1?'addon/shop/discount/nav-right.png':'addon/shop/discount/nav-center.png')" />
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<mescroll-body v-if="discountList.length" ref="mescrollRef" :top="mescrollTop" @init="mescrollInit" :down="{ use: false }" @up="getActiveDiscountGoodsListFn">
|
|
||||||
<view class="sidebar-margin py-[var(--top-m)] bg-[#F4F6F8]">
|
|
||||||
<block v-for="(item,index) in list" :key="index">
|
|
||||||
<view class="bg-[#fff] p-[20rpx] flex rounded-[var(--rounded-big)]" :class="{'mb-[var(--top-m)]':index<list.length-1}" @click="toLink(item)">
|
|
||||||
<view class="w-[240rpx] h-[240rpx] rounded-[var(--goods-rounded-big)] overflow-hidden">
|
|
||||||
<u--image width="240rpx" height="240rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.goods_cover_thumb_mid ? item.goods_cover_thumb_mid : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="rounded-[var(--goods-rounded-big)] overflow-hidden w-[240rpx] h-[240rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="ml-[20rpx] flex-1 flex flex-col justify-between">
|
|
||||||
<view class="text-[28rpx] leading-[1.4] multi-hidden">
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length" class="flex flex-wrap mb-[auto]">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="relative overflow-hidden w-full h-[88rpx] flex justify-between mt-[20rpx] rounded-[100rpx]" :class="{'bg-[var(--primary-color-light)]': item.activeGoods.active_goods_status=='active','bg-[#FFF6F1]': item.activeGoods.active_goods_status!='active' }">
|
|
||||||
<view class="mr-[20rpx] pl-[30rpx] flex-1 flex flex-col justify-center">
|
|
||||||
<view class="flex items-end">
|
|
||||||
<view class="text-[var(--price-text-color)] flex items-baseline" :class="{'!text-[#FF8540]':item.activeGoods.active_goods_status!='active'}">
|
|
||||||
<text class="text-[26rpx] leading-[26rpx] font-500 mr-[4rpx] price-font">¥</text>
|
|
||||||
<text class="text-[44rpx] leading-[40rpx] font-500 price-font">{{parseFloat(item.goodsSku.active_discount_price).toFixed(2).split('.')[0]}}.</text>
|
|
||||||
<text class="text-[26rpx] leading-[28rpx] font-500 price-font">{{parseFloat(item.goodsSku.active_discount_price).toFixed(2).split('.')[1]}}</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goodsSku.active_discount_rate<10" class="mb-[4rpx] text-[var(--price-text-color)] px-[4rpx] border-[1rpx] border-[var(--primary-color)] border-solid text-[18rpx] ml-[4rpx] rounded-[4rpx] leading-[24rpx]" :class="{'!border-[#FF8540]':item.activeGoods.active_goods_status!='active'}">{{item.goodsSku.active_discount_rate}}折</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center mt-[4rpx]">
|
|
||||||
<view class="w-[20rpx] h-[20rpx] mr-[4rpx] rounded-[20rpx] text-[#fff] bg-[var(--primary-color)] flex items-center justify-center" :class="{'!bg-[#FF8540]':item.activeGoods.active_goods_status!='active'}">
|
|
||||||
<text class="text-[10rpx] nc-icon-biaoqianV6mm1 nc-iconfont"></text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[18rpx] font-400 text-[var(--price-text-color)] leading-[24rpx]" :class="{'!text-[#FF8540]':item.activeGoods.active_goods_status!='active'}">已省{{item.goodsSku.active_reduce_money}}元</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="discount-btn text-[#ff763b] iconfont iconUnion" v-if="item.activeGoods.active_goods_status!='active'">
|
|
||||||
<text class="desc">{{item.activeGoods.active_goods_status_name}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="discount-btn text-[#fb3f15] iconfont iconUnion" v-else>
|
|
||||||
<text class="icon iconfont iconqiang"></text>
|
|
||||||
<text class="arrow iconxiayibu iconfont"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<mescroll-empty v-if="!list.length && !loading" :option="{tip : '暂无商品,请看看其他商品吧!'}"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
</mescroll-body>
|
|
||||||
|
|
||||||
<view v-if="!discountList.length && !loading" class="h-[calc(100vh-550rpx)]" :style="{'padding-top':mescrollTop}">
|
|
||||||
<mescroll-empty :option="{tip : '暂无商品,请看看其他商品吧!','btnText': '去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/goods/list' })"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
<loading-page :loading="bannerListLoading"></loading-page>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import { img, redirect, getToken, currRoute, diyRedirect,pxToRpx } from '@/utils/common';
|
|
||||||
import { getActiveDiscountConfig,getActiveDiscountList,getActiveDiscountGoodsList } from '@/addon/shop/api/discount'
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
|
|
||||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const headStyle = computed(() => {
|
|
||||||
let style = Object.keys(menuButtonInfo).length ? (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + pxToRpx(8) + 368) + 'rpx' : '490rpx'
|
|
||||||
return style
|
|
||||||
})
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
|
|
||||||
const bannerList: any = ref<Array<Object>>([])
|
|
||||||
const discountList = ref<Array<Object>>([])
|
|
||||||
const active = ref<number>(0)
|
|
||||||
const active_name = ref<String>('')
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
const bannerListLoading = ref<boolean>(true);
|
|
||||||
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let param = topTabarObj.setTopTabbarParam({title:'限时折扣'})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
const imgList:any = ref([])
|
|
||||||
|
|
||||||
const getActiveDiscountConfigFn = ()=>{
|
|
||||||
bannerListLoading.value = true
|
|
||||||
getActiveDiscountConfig().then((res:any)=>{
|
|
||||||
bannerList.value = res.data
|
|
||||||
imgList.value = bannerList.value.map((el: any)=>img(el.imageUrl))
|
|
||||||
bannerListLoading.value = false
|
|
||||||
}).catch(()=>{
|
|
||||||
bannerListLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getActiveDiscountConfigFn()
|
|
||||||
const getActiveDiscountListFn = ()=>{
|
|
||||||
getActiveDiscountList({}).then((res:any)=>{
|
|
||||||
discountList.value = res.data
|
|
||||||
calculateHeight();
|
|
||||||
if(discountList.value&&discountList.value.length){
|
|
||||||
navClick(res.data[0]);
|
|
||||||
}else{
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
getActiveDiscountListFn()
|
|
||||||
const navClick = (item:any)=>{
|
|
||||||
active.value = item.active_id
|
|
||||||
active_name.value = item.active_status_name
|
|
||||||
getMescroll()?.resetUpScroll();
|
|
||||||
uni.pageScrollTo({
|
|
||||||
scrollTop: 0, //距离页面顶部的距离
|
|
||||||
duration: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const getActiveDiscountGoodsListFn = (mescroll: any) => {
|
|
||||||
if(discountList.value.length == 0) return;
|
|
||||||
|
|
||||||
loading.value = true;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
active_id:active.value
|
|
||||||
};
|
|
||||||
|
|
||||||
getActiveDiscountGoodsList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>).map((el: any) => {return el})
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const toRedirect =(index:any)=>{
|
|
||||||
let data = bannerList.value[index].toLink
|
|
||||||
if (Object.keys(data).length) {
|
|
||||||
if (!data.name) return;
|
|
||||||
if (currRoute() == 'app/pages/member/index' && !getToken()) {
|
|
||||||
useLogin().setLoginBack({ url: data.url })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
diyRedirect(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (item : any) => {
|
|
||||||
if (item.activeGoods.active_goods_status != 'active') {
|
|
||||||
uni.showToast({ title: `活动${ item.activeGoods.active_goods_status_name }`, icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { sku_id: item.goodsSku.sku_id, type: 'discount' } })
|
|
||||||
}
|
|
||||||
|
|
||||||
const mescrollTop = ref('')
|
|
||||||
const calculateHeight = ()=>{
|
|
||||||
mescrollTop.value = Object.keys(menuButtonInfo).length ? (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + pxToRpx(8) + 368)+(discountList.value.length?70:0) + 'rpx' : (discountList.value.length?'560rpx':'490rpx')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
.swiper.ns-indicator-dots :deep(.uni-swiper-dots-horizontal) {
|
|
||||||
bottom:40rpx
|
|
||||||
}
|
|
||||||
.swiper.ns-indicator-dots :deep(.uni-swiper-dot) {
|
|
||||||
background-color: #fff;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.swiper.ns-indicator-dots :deep(.uni-swiper-dot-active) {
|
|
||||||
background-color: #fff;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.active{
|
|
||||||
padding: 0 14rpx;
|
|
||||||
line-height: 34rpx;
|
|
||||||
border-radius: 29rpx;
|
|
||||||
background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;
|
|
||||||
}
|
|
||||||
.active-button{
|
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
:deep(.u-swiper-indicator__wrapper--line__bar){
|
|
||||||
height: 5rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-swiper-indicator__wrapper--line){
|
|
||||||
height: 5rpx !important;
|
|
||||||
}
|
|
||||||
.discount-btn{
|
|
||||||
font-size: 88rpx;
|
|
||||||
margin-left: auto;
|
|
||||||
position: absolute;
|
|
||||||
right: -2rpx;
|
|
||||||
display: flex;
|
|
||||||
line-height: 1;
|
|
||||||
.icon{
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
left: 40rpx;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 44rpx;
|
|
||||||
}
|
|
||||||
.arrow{
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: #fff;
|
|
||||||
right: 18rpx;
|
|
||||||
font-size: 16rpx;
|
|
||||||
}
|
|
||||||
.desc{
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
left: 34rpx;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 26rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<view v-for="(item, index) in value" class="mb-[18rpx] relative" :class="{'mr-[18rpx]': (index + 1) % 4 != 0 }">
|
|
||||||
<u--image class="rounded-[10rpx] overflow-hidden" width="140rpx" height="140rpx" :src="img(item || '')" model="aspectFill" @click="imgListPreview(item)">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="absolute top-0 right-[0] bg-[#373737] flex justify-end h-[28rpx] w-[28rpx] rounded-bl-[40rpx]" @click.stop="deleteImg(index)">
|
|
||||||
<text class="nc-iconfont nc-icon-guanbiV6xx !text-[20rpx] mt-[2rpx] mr-[2rpx] text-[#fff]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[140rpx] h-[140rpx]" v-show="value.length < maxCount">
|
|
||||||
<u-upload @afterRead="afterRead" :maxCount="maxCount" :multiple="prop.multiple">
|
|
||||||
<view class="flex items-center justify-center w-[140rpx] h-[140rpx] border-[2rpx] border-dashed border-[#ddd] text-center text-[var(--text-color-light9)] rounded-[var(--goods-rounded-big)]">
|
|
||||||
<view>
|
|
||||||
<view class="nc-iconfont nc-icon-xiangjiV6xx text-[50rpx]"></view>
|
|
||||||
<view class="text-[24rpx] mt-[12rpx]">{{ value.length }}/{{ maxCount }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-upload>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed } from 'vue';
|
|
||||||
import { img } from '@/utils/common';
|
|
||||||
import { uploadImage } from '@/app/api/system'
|
|
||||||
|
|
||||||
const prop = defineProps({
|
|
||||||
modelValue: {
|
|
||||||
type: String || Array,
|
|
||||||
},
|
|
||||||
maxCount: {
|
|
||||||
type: Number,
|
|
||||||
default: 9
|
|
||||||
},
|
|
||||||
multiple: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
const value: any = computed({
|
|
||||||
get() {
|
|
||||||
return prop.modelValue
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
emit('update:modelValue', value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const maxCount = computed(() => {
|
|
||||||
return prop.maxCount
|
|
||||||
})
|
|
||||||
const afterRead = (event:any) => {
|
|
||||||
if (prop.multiple) {
|
|
||||||
event.file.forEach((file: any) => {
|
|
||||||
upload({ file })
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
upload(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const upload = (event:any) => {
|
|
||||||
if (value.value?.length >= maxCount.value) {
|
|
||||||
uni.showToast({ title: `最多允许上传${maxCount.value}张图片`, icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadImage({
|
|
||||||
filePath: event.file.url,
|
|
||||||
name: 'file'
|
|
||||||
}).then(res => {
|
|
||||||
if (value.value?.length < maxCount.value) value.value.push(res.data.url)
|
|
||||||
}).catch(() => {
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteImg = (index:number)=>{
|
|
||||||
value.value.splice(index,1)
|
|
||||||
}
|
|
||||||
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item:any) => {
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" :style="themeColor()">
|
|
||||||
<view class="fixed left-0 top-0 right-0 z-10">
|
|
||||||
<scroll-view scroll-x="true" class="tab-style-2">
|
|
||||||
<view class="tab-content">
|
|
||||||
<view class="tab-items" :class="{ 'class-select': evaluateStatus === item.status }" @click="statusClickFn(item.status, item.value)" v-for="(item, index) in statusList">{{ item.name }}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<mescroll-body ref="mescrollRef" top="88rpx" @init="mescrollInit" :down="{ use: false }" @up="getEvaluateListFn">
|
|
||||||
<view class="sidebar-margin pt-[var(--top-m)]" v-if="list.length">
|
|
||||||
<template v-for="(item, index) in list">
|
|
||||||
<view class="mb-[var(--top-m)] card-template !pb-[20rpx]">
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<u-avatar :src="img(item.member_head)" :default-url="img('static/resource/images/default_headimg.png')" :size="'50rpx'" leftIcon="none" />
|
|
||||||
<text class="text-[30rpx] font-500 ml-[10rpx]">{{ item.member_name }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)]">{{ item.create_time ? item.create_time.slice(0, 10) : '' }}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="pt-[30rpx] flex items-center">
|
|
||||||
<u-rate :count="5" v-model="item.scores" active-color="var(--primary-color)" :size="'36rpx'" gutter="1" readonly></u-rate>
|
|
||||||
<text class="ml-[20rpx] text-[26rpx] text-[var(--text-color-light9)]">{{ item.scores === 1 ? '差评' : item.scores === 2 || item.scores === 3 ? '中评' : '好评' }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[28rpx] break-all leading-[1.2] text-[#333] my-[20rpx] overflow-clip">{{ item.content }}</view>
|
|
||||||
<template v-if="item.image_mid.length === 1">
|
|
||||||
<view class="w-[420rpx] mt-[10rpx]">
|
|
||||||
<u--image width="420rpx" height="420rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length === 2">
|
|
||||||
<view class="flex justify-between mt-[10rpx]">
|
|
||||||
<view class="w-[322rpx]">
|
|
||||||
<u--image width="322rpx" height="322rpx" :src="img(item.image_mid[0])" :radius="'var(--goods-rounded-big)'" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="w-[322rpx]">
|
|
||||||
<u--image width="322rpx" height="322rpx" :src="img(item.image_mid[1])" :radius="'var(--goods-rounded-big)'" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length === 3">
|
|
||||||
<view class="flex justify-between mt-[10rpx]">
|
|
||||||
<u--image width="430rpx" height="430rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view>
|
|
||||||
<u--image width="205rpx" height="205rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[1])" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="mt-[20rpx]">
|
|
||||||
<u--image width="205rpx" height="205rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[2])" model="aspectFill" @click="imgListPreview(item.images[2])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-if="item.image_mid.length === 4">
|
|
||||||
<view class="flex flex-wrap mt-[10rpx]">
|
|
||||||
<view class="mr-[15rpx] mb-[15rpx]">
|
|
||||||
<u--image width="215rpx" height="215rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="mr-[15rpx] mb-[15rpx]">
|
|
||||||
<u--image width="215rpx" height="215rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[1])" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="mr-[15rpx]">
|
|
||||||
<u--image width="215rpx" height="215rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[2])" model="aspectFill" @click="imgListPreview(item.images[2])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="mr-[15rpx]">
|
|
||||||
<u--image width="215rpx" height="215rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.image_mid[3])" model="aspectFill" @click="imgListPreview(item.images[3])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length > 4">
|
|
||||||
<view class="flex flex-wrap mt-[10rpx]">
|
|
||||||
<view v-for="(imageItem, imageIndex) in item.image_mid" class="mb-[10rpx]" :class="{'mr-[10rpx]':(imageIndex + 1) % 3 != 0}">
|
|
||||||
<u--image width="211rpx" height="211rpx" :src="img(imageItem)" model="aspectFill" :radius="'var(--goods-rounded-big)'" @click="imgListPreview(item.images[imageIndex])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="var(--text-color-light9)" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<view v-if="item.explain_first !=''" class="text-[26rpx] !text-[var(--text-color-light6)] mt-[20rpx] pt-[20rpx] border-0 border-t-[2rpx] border-solid border-[#ebebec] w-[100%] overflow-clip leading-[1.2] break-all">
|
|
||||||
<text class=" text-[var(--primary-color)]">商家回复:</text>{{ item.explain_first }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!list.length && loading" :option="{tip : '暂无评价'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<pay ref="payRef"></pay>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { img } from '@/utils/common'
|
|
||||||
import { getEvaluateList } from '@/addon/shop/api/evaluate'
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
|
|
||||||
import { onLoad, onUnload,onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const statusList = <Array<Object>>([
|
|
||||||
{ status: 1, name: '全部', value: [] },
|
|
||||||
{ status: 2, name: '好评', value: [4, 5] },
|
|
||||||
{ status: 3, name: '中评', value: [2, 3] },
|
|
||||||
{ status: 4, name: '差评', value: [1] },
|
|
||||||
]);
|
|
||||||
const evaluateStatus = ref(1);
|
|
||||||
const evaluateValue = ref([]);
|
|
||||||
const goodsId = ref('')
|
|
||||||
onLoad((option: any) => {
|
|
||||||
goodsId.value = option.goods_id || ''
|
|
||||||
})
|
|
||||||
|
|
||||||
const statusClickFn = (status: any, value: any) => {
|
|
||||||
evaluateStatus.value = status;
|
|
||||||
evaluateValue.value = value
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getEvaluateListFn = (mescroll:any) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
goods_id: goodsId.value,
|
|
||||||
scores: evaluateValue.value
|
|
||||||
};
|
|
||||||
|
|
||||||
getEvaluateList(data).then((res:any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item:any) => {
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//关闭预览图片
|
|
||||||
onUnload(()=>{
|
|
||||||
// #ifdef H5 || APP
|
|
||||||
uni.closePreviewImage()
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
height: 6rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
width: 90%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen" :style="themeColor()">
|
|
||||||
<view class="px-[var(--sidebar-m)] py-[var(--top-m)]">
|
|
||||||
<template v-for="(item, index) in info" :key="index">
|
|
||||||
<view class="card-template mb-[var(--top-m)]">
|
|
||||||
<view class="bg-[var(--temp-bg)] p-[20rpx] rounded-[var(--rounded-mid)] flex">
|
|
||||||
<u--image radius="var(--goods-rounded-mid)" width="150rpx" height="150rpx" :src="img(item.goods_image_thumb_small ? item.goods_image_thumb_small : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex-1 flex flex-wrap ml-[20rpx] my-[4rpx]">
|
|
||||||
<view>
|
|
||||||
<view class="text-[26rpx] leading-[40rpx] max-w-[450rpx] truncate">{{ item.goods_name }}</view>
|
|
||||||
<view class="max-w-[450rpx] mt-[14rpx] truncate text-[22rpx] text-[var(--text-color-light9)] leading-[28rpx]" v-if="item.sku_name">{{ item.sku_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-auto w-full flex justify-between items-center">
|
|
||||||
<view class="flex items-baseline price-font">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(item.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(item.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="font-400 text-[28rpx] text-[#333]">x{{ item.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center mt-[30rpx]">
|
|
||||||
<u-rate :count="5" v-model="form[index].scores" active-color="var(--primary-color)" :size="'36rpx'" gutter="1"></u-rate>
|
|
||||||
<text class="ml-[16rpx] text-[28rpx] pt-[2rpx] text-[var(--primary-color)]">{{ form[index].scores === 1 ? '差评' : form[index].scores === 2 || form[index].scores === 3 ? '中评' : '好评' }}</text>
|
|
||||||
</view>
|
|
||||||
<textarea
|
|
||||||
class="!text-[26rpx] px-[2rpx] mt-[16rpx] w-[100%] !text-[#333] !leading-[1.5]"
|
|
||||||
v-model.trim="form[index].content" placeholder="请在此处输入你的评价" placeholderClass="text-[26rpx] text-[var(--text-color-light9)]" maxlength="200" />
|
|
||||||
<!-- <view class="text-right text-[24rpx] text-[var(--text-color-light6)]">{{ form[index].content.length >= 200 ? 200 : form[index].content.length }}/200</view> -->
|
|
||||||
<upload-img class="mt-[20rpx]" v-model="form[index].images" :max-count="9" :multiple="true" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" zIndex="9999">
|
|
||||||
<view class="flex items-center pl-[30rpx] pr-[20rpx] box-border justify-between w-[100%]">
|
|
||||||
<view class="flex items-center" @click="selectCheck">
|
|
||||||
<text class="iconfont text-color text-[30rpx] mr-[12rpx] text-[var(--text-color-light9)]"
|
|
||||||
:class="{'iconxuanze1 text-[var(--primary-color)]' : is_anonymous === '1' ,'nc-iconfont nc-icon-yuanquanV6xx':is_anonymous !== '1'}"></text>
|
|
||||||
<text class="text-[28rpx] leading-[34rpx]"
|
|
||||||
:class="{'text-[var(--primary-color)]' :is_anonymous === '1', 'text-[var(--text-color-light6)]':is_anonymous !== '1'}">匿名</text>
|
|
||||||
</view>
|
|
||||||
<button
|
|
||||||
class="!w-[240rpx] !h-[70rpx] text-[26rpx] !m-0 flex-center rounded-full text-white primary-btn-bg remove-border font-500"
|
|
||||||
hover-class="none" @click="submit">提交</button>
|
|
||||||
</view>
|
|
||||||
</u-tabbar>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref,nextTick } from 'vue';
|
|
||||||
import { getShopOrderDetail } from '@/addon/shop/api/order';
|
|
||||||
import { setOrderEvaluate } from '@/addon/shop/api/evaluate';
|
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
|
||||||
import { img, redirect, goback } from '@/utils/common';
|
|
||||||
import uploadImg from '@/addon/shop/pages/evaluate/components/upload-img'
|
|
||||||
|
|
||||||
const info = ref<Array<any>>([])
|
|
||||||
const form = ref<Array<any>>([])
|
|
||||||
const is_anonymous = ref('2')
|
|
||||||
const loading = ref(false)
|
|
||||||
const order_id = ref('')
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
if(option.order_id){
|
|
||||||
order_id.value = option.order_id
|
|
||||||
getShopOrderDetailFn(order_id.value)
|
|
||||||
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/order/list',
|
|
||||||
param: {
|
|
||||||
status: 5
|
|
||||||
},
|
|
||||||
title: '缺少订单id'
|
|
||||||
};
|
|
||||||
goback(parameter)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const getShopOrderDetailFn = (id: any) => {
|
|
||||||
loading.value = true
|
|
||||||
getShopOrderDetail(id).then((res: any) => {
|
|
||||||
if (res.data.is_evaluate) {
|
|
||||||
toLink(order_id.value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
res.data.order_goods.forEach((el: any) => {
|
|
||||||
if (el.status != 1 || el.is_enable_refund == 1) {
|
|
||||||
// 排除存在退款的情况
|
|
||||||
}else {
|
|
||||||
info.value.push(el);
|
|
||||||
form.value.push({
|
|
||||||
order_id: el.order_id,
|
|
||||||
order_goods_id: el.order_goods_id,
|
|
||||||
goods_id: el.goods_id,
|
|
||||||
content: '',
|
|
||||||
images: [],
|
|
||||||
scores: 5
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
loading.value = false
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectCheck = () => {
|
|
||||||
is_anonymous.value = is_anonymous.value === '1' ? '2' : '1'
|
|
||||||
}
|
|
||||||
|
|
||||||
const submit = () => {
|
|
||||||
if (form.value.some(el => el.content == '')) {
|
|
||||||
uni.showToast({ title: '请输入你的评价', icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for (let i = 0; i < form.value.length; i++) {
|
|
||||||
let item = form.value[i];
|
|
||||||
if (item.content.length > 200) {
|
|
||||||
item.content = item.content.substr(0, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
form.value.forEach(v => v.is_anonymous = is_anonymous.value)
|
|
||||||
loading.value = true
|
|
||||||
setOrderEvaluate({ evaluate_array: form.value }).then(res => {
|
|
||||||
loading.value = false
|
|
||||||
toLink(order_id.value)
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (order_id : any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate_view', param: { order_id }, mode: 'redirectTo' })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss">
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen" :style="themeColor()">
|
|
||||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getShopOrderFn">
|
|
||||||
<view class="px-[var(--sidebar-m)] py-[var(--top-m)]" v-if="info.length">
|
|
||||||
<template v-for="(item, index) in info" :key="index">
|
|
||||||
<view class="card-template mb-[var(--top-m)]">
|
|
||||||
<view class="bg-[var(--temp-bg)] p-[20rpx] rounded-[var(--rounded-mid)] flex" @click="redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: item.goods_id } })">
|
|
||||||
<u--image radius="var(--goods-rounded-mid)" width="150rpx" height="150rpx" :src="img(item.order_goods.goods_image_thumb_mid ? item.order_goods.goods_image_thumb_mid : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex-1 flex flex-wrap ml-[20rpx] my-[4rpx]">
|
|
||||||
<view>
|
|
||||||
<view class="text-[26rpx] leading-[40rpx] max-w-[450rpx] truncate">{{ item.order_goods.goods_name }}</view>
|
|
||||||
<view class="max-w-[450rpx] mt-[14rpx] truncate text-[22rpx] text-[var(--text-color-light9)] leading-[28rpx]" v-if="item.order_goods.sku_name">{{ item.order_goods.sku_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-auto w-full flex justify-between items-center">
|
|
||||||
<view class="flex items-baseline price-font">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(item.order_goods.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(item.order_goods.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="font-400 text-[28rpx] text-[#333]">x{{ item.order_goods.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center mt-[30rpx]">
|
|
||||||
<u-rate :count="5" v-model="item.scores" active-color="var(--primary-color)" :size="'36rpx'" gutter="1" readonly></u-rate>
|
|
||||||
<text class="ml-[16rpx] text-[28rpx] pt-[2rpx] text-[var(--primary-color)]">{{ item.scores === 1 ? '差评' : item.scores === 2 || item.scores === 3 ? '中评' : '好评' }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="px-[2rpx] text-[28rpx] text-[#333] mt-[16rpx] mb-[20rpx] break-all leading-[1.5]">{{ item.content }}</view>
|
|
||||||
<template v-if="item.image_mid.length === 1">
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mt-[10rpx]" width="420rpx" height="420rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length === 2">
|
|
||||||
<view class="flex justify-between mt-[10rpx]">
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden" width="322rpx" height="322rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden" width="322rpx" height="322rpx" :src="img(item.image_mid[1])" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length === 3">
|
|
||||||
<view class="flex justify-between mt-[10rpx]">
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden" width="430rpx" height="430rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mb-[20rpx]" width="205rpx" height="205rpx" :src="img(item.image_mid[1])" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden" width="205rpx" height="205rpx" :src="img(item.image_mid[2])" model="aspectFill" @click="imgListPreview(item.images[2])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length === 4">
|
|
||||||
<view class="flex flex-wrap mt-[10rpx]">
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mr-[15rpx] mb-[15rpx]" width="215rpx" height="215rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mr-[15rpx] mb-[15rpx]" width="215rpx" height="215rpx" :src="img(item.image_mid[1])" model="aspectFill" @click="imgListPreview(item.images[1])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mr-[15rpx]" width="215rpx" height="215rpx" :src="img(item.image_mid[2])" model="aspectFill" @click="imgListPreview(item.images[2])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<u--image class="rounded-[var(--goods-rounded-big)] overflow-hidden mr-[15rpx]" width="215rpx" height="215rpx" :src="img(item.image_mid[3])" model="aspectFill" @click="imgListPreview(item.images[3])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.image_mid.length > 4">
|
|
||||||
<view class="flex flex-wrap mt-[10rpx]">
|
|
||||||
<u--image v-for="(imageItem, imageIndex) in item.images"
|
|
||||||
:class="['rounded-[var(--goods-rounded-big)] overflow-hidden mb-[10rpx]', (imageIndex + 1) % 3 === 0 ? '' : 'mr-[10rpx]']"
|
|
||||||
width="211rpx" height="211rpx" :src="img(imageItem)" model="aspectFill"
|
|
||||||
@click="imgListPreview(imageItem)">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<view v-if="item.explain_first !=''" class="text-[26rpx] !text-[var(--text-color-light6)] mt-[20rpx] pt-[20rpx] border-0 border-t-[2rpx] border-solid border-[#F1F2F5] w-[100%] overflow-clip leading-[34rpx] break-all">
|
|
||||||
<text class="text-[var(--primary-color)]">商家回复:</text>
|
|
||||||
<text>{{ item.explain_first }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!info.length && !loading" :option="{tip : '暂无评价'}" ></mescroll-empty>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
</mescroll-body>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { getOrderEvaluate } from '@/addon/shop/api/evaluate';
|
|
||||||
import { onLoad,onUnload,onPageScroll,onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import { img, redirect, goback } from '@/utils/common';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const info = ref<Array<any>>([])
|
|
||||||
const loading = ref(true)
|
|
||||||
onLoad((option:any) => {
|
|
||||||
if(option.order_id){
|
|
||||||
getOrderEvaluateFn(option.order_id)
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/evaluate/list',
|
|
||||||
title: '缺少订单id'
|
|
||||||
};
|
|
||||||
goback(parameter)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const getOrderEvaluateFn = (id: any) => {
|
|
||||||
loading.value = true
|
|
||||||
getOrderEvaluate(id).then((res: any) => {
|
|
||||||
info.value = res.data
|
|
||||||
loading.value = false
|
|
||||||
}).catch(()=>{
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item:any) => {
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭预览图片
|
|
||||||
onUnload(()=>{
|
|
||||||
// #ifdef H5 || APP
|
|
||||||
uni.closePreviewImage()
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" :style="themeColor()">
|
|
||||||
<view class="fixed top-0 left-0 right-0 z-200">
|
|
||||||
<view class="tab-style-1 py-[20rpx] bg-[#fff] border-0 border-solid border-b-[1rpx] border-[#f6f6f6] ">
|
|
||||||
<view class="tab-left text-[28rpx]">
|
|
||||||
<text>共</text>
|
|
||||||
<text class="text-primary">{{ browseTotal }}</text>
|
|
||||||
<text>条</text>
|
|
||||||
</view>
|
|
||||||
<view class="tab-right !items-center">
|
|
||||||
<view class="flex items-center" @click="handleSelect">
|
|
||||||
<view class="tab-right-date">日期</view>
|
|
||||||
<view class="nc-iconfont nc-icon-a-riliV6xx-36 tab-right-icon"></view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[2rpx] h-[28rpx] mx-[20rpx] bg-gradient-to-b from-[#333] to-[#fff]"></view>
|
|
||||||
<view @click="isEdit = !isEdit" class="text-[#333] text-[28rpx]">{{ isEdit ? '完成' : '管理' }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-body ref="mescrollRef" top="76" bottom="168" @init="mescrollInit" :down="{ use: false }" @up="getBrowseListFn">
|
|
||||||
<view v-if="browseList.length">
|
|
||||||
<view class="bg-[#fff] mb-[20rpx] pt-[30rpx] px-[20rpx]" v-for="(item,index) in browseList" :key="index">
|
|
||||||
<view class="flex items-center h-[34rpx] mb-[20rpx]">
|
|
||||||
<view class="self-center w-[58rpx] flex items-center" v-if="isEdit" @click.stop="isSelectGroup(item)">
|
|
||||||
<view class="bg-[#fff] w-[34rpx] h-[34rpx] rounded-[17rpx] flex items-center justify-center">
|
|
||||||
<text class=" iconfont text-primary text-[34rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0" :class="{ 'iconxuanze1':item.checked,'bg-[#F5F5F5]':!item.checked}" >
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[28rpx] font-500 text-[#333] ">{{ item.date }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<view class="w-[230rpx] mb-[20rpx]" :class="{'mr-[10rpx]': (subIndex + 1) % 3 }" v-for="(subItem,subIndex) in item.list" :key="subIndex" @click="toDetail(subItem)">
|
|
||||||
<view class="relative w-[230rpx] h-[230rpx] rounded-[var(--goods-rounded-mid)] overflow-hidden mb-[10rpx]">
|
|
||||||
<u--image width="230rpx" height="230rpx" :radius="'var(--goods-rounded-mid)'" :src="img(subItem.goods_cover_thumb_mid ? subItem.goods_cover_thumb_mid : '')" mode="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[230rpx] h-[230rpx] rounded-[var(--goods-rounded-mid)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view v-if="subItem.status == 0 " class="absolute left-0 top-0 w-[230rpx] h-[230rpx] leading-[230rpx] text-center " style="background-color: rgba(0,0,0,0.3);">
|
|
||||||
<text class="text-[#fff] text-[28rpx]">已失效</text>
|
|
||||||
</view>
|
|
||||||
<view class="absolute top-0 left-0 right-0 bottom-0 p-[10rpx] flex justify-end items-start z-100" v-if="isEdit" @click.stop="changeItem(item,subItem)">
|
|
||||||
<view class="bg-[#fff] w-[34rpx] h-[34rpx] rounded-[17rpx] flex items-center justify-center">
|
|
||||||
<text class="iconfont text-primary text-[34rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0" :class="{ 'iconxuanze1':subItem.checked,'bg-[#F5F5F5]':!subItem.checked}"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(subItem.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(subItem.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!browseList.length && loading" :option="{tip : '暂无浏览的商品'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<view v-if="browseList.length && isEdit" class="fixed left-0 right-0 bottom-0 z-200 bg-[#fff] pb-ios">
|
|
||||||
<view v-if="checkedNum" class="h-[66rpx] flex items-center justify-between pl-[30rpx] pr-[20rpx] border-0 border-b-[1rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="text-[24rpx]">
|
|
||||||
<text>已选</text>
|
|
||||||
<text class="text-primary">{{ checkedNum }}</text>
|
|
||||||
<text>件宝贝</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] text-[#999]" @click="clearBrowseFn">一键清空宝贝足迹</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex h-[100rpx] items-center justify-between pl-[30rpx] pr-[20rpx]">
|
|
||||||
<view class="flex items-center" @click="allChange">
|
|
||||||
<text class="self-center iconfont text-primary text-[34rpx] mr-[10rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden flex-shrink-0" :class="{'iconxuanze1': isSelectAll, 'bg-color': !isSelectAll } "></text>
|
|
||||||
<text class="font-400 text-[#303133] text-[26rpx]">全选</text>
|
|
||||||
</view>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="deleteBrowseFn">删除</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 时间选择 -->
|
|
||||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { img, redirect } from '@/utils/common';
|
|
||||||
import { getBrowse, delBrowse } from '@/addon/shop/api/goods';
|
|
||||||
import selectDate from '@/components/select-date/select-date.vue';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
|
|
||||||
const isEdit = ref(false)
|
|
||||||
let loading = ref<boolean>(false);
|
|
||||||
const optionLoading = ref(false)
|
|
||||||
const browseTotal = ref<number>(0);
|
|
||||||
let browseList = ref<any>([]);
|
|
||||||
const create_time = ref([])
|
|
||||||
let dateList = ref<any>([])
|
|
||||||
const getBrowseListFn = (mescroll: any) =>{
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
date: create_time.value
|
|
||||||
};
|
|
||||||
getBrowse(data).then((res: any) => {
|
|
||||||
browseTotal.value = res.data.total;
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (Number(mescroll.num) === 1) {
|
|
||||||
browseList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
// 按日期分组
|
|
||||||
const groupedData = newArr.reduce((acc: any, item: any) => {
|
|
||||||
const date = item.browse_time.split(' ')[0]; // 提取日期部分
|
|
||||||
if (!acc[date]) {
|
|
||||||
acc[date] = [];
|
|
||||||
}
|
|
||||||
acc[date].push(item);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// 转换为所需格式
|
|
||||||
const formattedData = Object.keys(groupedData).map(date => ({
|
|
||||||
date: date,
|
|
||||||
list: groupedData[date]
|
|
||||||
}));
|
|
||||||
formattedData.forEach((item: any) => {
|
|
||||||
item.checked = false;
|
|
||||||
item.list.forEach((subItem: any)=> {
|
|
||||||
subItem.checked = false; // 初始化选中状态
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 合并相同日期的数据
|
|
||||||
formattedData.forEach((newItem: any) => {
|
|
||||||
const existingItemIndex = browseList.value.findIndex((item: any) => item.date === newItem.date);
|
|
||||||
if (existingItemIndex !== -1) {
|
|
||||||
// 合并到已有的日期数据中
|
|
||||||
browseList.value[existingItemIndex].list = [...browseList.value[existingItemIndex].list, ...newItem.list];
|
|
||||||
} else {
|
|
||||||
// 新增日期数据
|
|
||||||
browseList.value.push(newItem);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 选择数量
|
|
||||||
const checkedNum = computed(() => {
|
|
||||||
let num = 0
|
|
||||||
browseList.value.forEach((item: any) => {
|
|
||||||
item.list.forEach((subItem: any)=>{
|
|
||||||
subItem.checked && (num += 1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return num
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全选
|
|
||||||
*/
|
|
||||||
//判断是否全选状态
|
|
||||||
const isSelectAll = ref(false)
|
|
||||||
const isallclick = ()=>{
|
|
||||||
const isActve = browseList.value.every((item: any) => {
|
|
||||||
return item.checked
|
|
||||||
})
|
|
||||||
if (isActve) { isSelectAll.value = true } else { isSelectAll.value= false }
|
|
||||||
}
|
|
||||||
// 选择每天的
|
|
||||||
const isSelectGroup = (data: any) =>{
|
|
||||||
data.checked = !data.checked
|
|
||||||
data.list.forEach((item :any) => {
|
|
||||||
item.checked = data.checked
|
|
||||||
})
|
|
||||||
isallclick()
|
|
||||||
}
|
|
||||||
// 全选
|
|
||||||
const allChange = () =>{
|
|
||||||
isSelectAll.value = !isSelectAll.value
|
|
||||||
browseList.value.forEach((item: any) => {
|
|
||||||
item.checked = isSelectAll.value
|
|
||||||
item.list.forEach((subItem: any) => {
|
|
||||||
subItem.checked = isSelectAll.value
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 选择单个商品
|
|
||||||
const changeItem = (data: any,value: any) =>{
|
|
||||||
value.checked = !value.checked
|
|
||||||
const isActve = data.list.every((item: any) => {
|
|
||||||
return item.checked
|
|
||||||
})
|
|
||||||
if (isActve) { data.checked = true } else { data.checked = false }
|
|
||||||
isallclick()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
const deleteBrowseFn = () => {
|
|
||||||
if (!checkedNum.value) {
|
|
||||||
uni.showToast({ title: '还没有选择商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
|
|
||||||
const ids: any = []
|
|
||||||
browseList.value.forEach((item: any) => {
|
|
||||||
item.list.forEach((subItem: any) => {
|
|
||||||
subItem.checked && ids.push(subItem.goods_id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
delBrowse({goods_ids: ids}).then((res: any) => {
|
|
||||||
optionLoading.value = false
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearBrowseFn = () => {
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
|
|
||||||
const ids: any = []
|
|
||||||
browseList.value.forEach((item: any) => {
|
|
||||||
item.list.forEach((subItem: any) => {
|
|
||||||
ids.push(subItem.goods_id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
delBrowse({goods_ids: ids}).then((res: any) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
optionLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//日期筛选
|
|
||||||
const selectDateRef = ref<any>(null)
|
|
||||||
const handleSelect = () =>{
|
|
||||||
selectDateRef.value.show = true
|
|
||||||
}
|
|
||||||
// 确定时间筛选
|
|
||||||
const confirmFn = (data: any) =>{
|
|
||||||
create_time.value = data;
|
|
||||||
browseList.value = []
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const toDetail = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.goods_id } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.bg-color{
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,703 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-page min-h-[100vh] overflow-hidden flex flex-col" v-if="!loading">
|
|
||||||
<view v-if="!info" class="pb-[100rpx]">
|
|
||||||
<view class="empty-page">
|
|
||||||
<image class="img" :src="img('static/resource/images/system/login.png')" model="aspectFit" />
|
|
||||||
<view class="desc">暂未登录</view>
|
|
||||||
<button shape="circle" plain="true" class="btn" @click="toLogin">去登录</button>
|
|
||||||
</view>
|
|
||||||
<ns-goods-recommend></ns-goods-recommend>
|
|
||||||
</view>
|
|
||||||
<view v-else-if="!cartList.length&&!invalidList.length" class="pb-[100rpx]">
|
|
||||||
<view class="empty-page">
|
|
||||||
<image class="img" :src="img('addon/shop/cart-empty.png')" model="aspectFit" />
|
|
||||||
<view class="desc">赶紧去逛逛, 购买心仪的商品吧</view>
|
|
||||||
<button shape="circle" plain="true" class="btn" @click="redirect({ url: '/addon/shop/pages/goods/list' })">去逛逛</button>
|
|
||||||
</view>
|
|
||||||
<ns-goods-recommend></ns-goods-recommend>
|
|
||||||
</view>
|
|
||||||
<block v-else>
|
|
||||||
<view class="flex-1 h-0">
|
|
||||||
<scroll-view class="scroll-height " :scroll-y="true">
|
|
||||||
<view class="py-[var(--top-m)] sidebar-margin">
|
|
||||||
<view class="bg-[#fff] pb-[10rpx] box-border rounded-[var(--rounded-big)]" v-if="cartList.length">
|
|
||||||
<view class="flex mx-[var(--rounded-big)] pt-[var(--pad-top-m)] justify-between items-center box-border font-400 text-[24rpx] mb-[24rpx] leading-[30rpx]">
|
|
||||||
<view class="flex items-baseline text-[24rpx] text-[#333]">
|
|
||||||
<text>共</text>
|
|
||||||
<text class="text-[32rpx] mx-[2rpx] text-[var(--price-text-color)]">{{ cartList.length }}</text>
|
|
||||||
<text>种商品</text>
|
|
||||||
</view>
|
|
||||||
<text @click="isEdit = !isEdit" class="text-[var(--text-color-light6)] text-[24rpx]">{{ isEdit ? '完成' : '管理' }}</text>
|
|
||||||
</view>
|
|
||||||
<u-swipe-action ref="swipeActive">
|
|
||||||
<block v-for="(item, index) in cartList">
|
|
||||||
<view v-if="item.goodsSku" class="py-[20rpx] overflow-hidden w-full">
|
|
||||||
<u-swipe-action-item :options="cartOptions" @click="swipeClick(index,item)">
|
|
||||||
<view class="flex px-[var(--pad-sidebar-m)]" @click.stop="selectOnlyGoods(item)">
|
|
||||||
<view class="self-center w-[34rpx] mr-[24rpx] h-[60rpx] flex items-center" @click.stop="selectOnlyGoods(item)">
|
|
||||||
<text
|
|
||||||
class=" iconfont text-color text-[34rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0"
|
|
||||||
:class="{ 'iconxuanze1':item.checked,'bg-[#F5F5F5]':!item.checked}">
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[200rpx] h-[200rpx] flex items-center justify-center rounded-[var(--goods-rounded-big)] overflow-hidden" @click="toDetail(item)">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="200rpx" height="200rpx" :src="img(item.goodsSku.sku_image_thumb_mid||'')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[200rpx] h-[200rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-col justify-between ml-[20rpx]">
|
|
||||||
<view class="w-[100%] flex flex-col items-baseline">
|
|
||||||
<view class="text-[#333] text-[28rpx] max-h-[80rpx] leading-[40rpx] multi-hidden font-400">
|
|
||||||
{{ item.goods.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view class="box-border max-w-[376rpx] mt-[10rpx] px-[14rpx] h-[36rpx] leading-[36rpx] truncate text-[var(--text-color-light6)] bg-[#F5F5F5] text-[22rpx] rounded-[20rpx]" v-if="item.goodsSku && item.goodsSku.sku_spec_format">
|
|
||||||
{{ item.goodsSku.sku_spec_format }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods && item.goods.goods_label_name && item.goods.goods_label_name.length" class="flex flex-wrap mb-[auto]">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.manjian_info && Object.keys(item.manjian_info).length && item.manjian_info.is_show" class="flex items-center mt-[8rpx] mb-[auto]" @click.stop="manjianOpenFn(item.manjian_info)">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[20rpx] flex items-center justify-center w-[88rpx] h-[36rpx] mr-[6rpx]">满减送</view>
|
|
||||||
<text class="text-[22rpx] text-[#999]">{{item.manjian_info.manjian_name}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-end self-end mt-[10rpx] w-[100%]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font truncate max-w-[200rpx]">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<u-number-box v-model="item.num" :min="numLimit(item).min"
|
|
||||||
:max="numLimit(item).max" integer :step="1" input-width="68rpx"
|
|
||||||
input-height="52rpx" button-size="52rpx" disabledInput
|
|
||||||
@change="numChange($event, index)">
|
|
||||||
<template #minus>
|
|
||||||
<view class="relative w-[26rpx] h-[26rpx]" @click="reduceNumChange(item)">
|
|
||||||
<text
|
|
||||||
:class="{ 'text-[var(--text-color-light9)]': item.num === numLimit(item).min, 'text-[#303133]': item.num !== numLimit(item).min }"
|
|
||||||
class="text-[24rpx] absolute flex items-center justify-center -left-[20rpx] -bottom-[20rpx] -right-[20rpx] -top-[20rpx] font-500 nc-iconfont nc-icon-jianV6xx"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template #input>
|
|
||||||
<input class="text-[#303133] text-[28rpx] mx-[14rpx] w-[80rpx] h-[44rpx] bg-[var(--temp-bg)] leading-[44rpx] text-center rounded-[6rpx]" type="number" @input="goodsSkuInputFn(item)" @blur="goodsSkuBlurFn($event, index)" @click.stop v-model="item.num" />
|
|
||||||
</template>
|
|
||||||
<template #plus>
|
|
||||||
<view class="relative w-[26rpx] h-[26rpx]" @click="addNumChange(item)">
|
|
||||||
<text
|
|
||||||
:class="{ 'text-[var(--text-color-light9)]': item.num === numLimit(item).max, ' text-[#303133]': item.num !== numLimit(item).max }"
|
|
||||||
class="text-[24rpx] absolute flex items-center justify-center -left-[20rpx] -bottom-[20rpx] -right-[20rpx] -top-[20rpx] font-500 nc-iconfont nc-icon-jiahaoV6xx"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</u-number-box>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-swipe-action-item>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
|
|
||||||
</u-swipe-action>
|
|
||||||
</view>
|
|
||||||
<view class="bg-[#fff] pb-[10rpx] box-border rounded-[var(--rounded-big)] mt-[var(--top-m)]" v-if="invalidList.length">
|
|
||||||
<view class="flex mx-[var(--pad-sidebar-m)] pt-[var(--pad-top-m)] justify-between items-center box-border font-400 text-[#303133] text-[24rpx] mb-[24rpx] leading-[30rpx]">
|
|
||||||
<view class="flex items-center text-[24rpx] text-[#333]">
|
|
||||||
<text>共</text>
|
|
||||||
<text class="text-[28rpx] text-[var(--price-text-color)]">{{ invalidList.length }}</text>
|
|
||||||
<text>件失效商品</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[var(--text-color-light6)] text-[24rpx]" @click="deleteInvalidList">清空</text>
|
|
||||||
</view>
|
|
||||||
<view v-for="(item, index) in invalidList" class="py-[20rpx] overflow-hidden" >
|
|
||||||
<view class="flex px-[var(--pad-sidebar-m)]">
|
|
||||||
<text class="self-center iconfont iconxuanze1 text-[34rpx] mr-[32rpx] text-[#F5F5F5] rounded-[50%] overflow-hidden shrink-0"></text>
|
|
||||||
<view class="relative w-[200rpx] h-[200rpx] rounded-[var(--goods-rounded-big)] overflow-hidden">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="200rpx" height="200rpx" :src="img(item.goodsSku.sku_image_thumb_mid)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[200rpx] h-[200rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view v-if="item.goodsSku.stock == 0 " class="absolute left-0 top-0 w-[200rpx] h-[200rpx] leading-[200rpx] text-center " style="background-color: rgba(0,0,0,0.3);">
|
|
||||||
<text class="text-[#fff] text-[28rpx]">已售罄</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goodsSku.stock != 0 " class="absolute left-0 top-0 w-[200rpx] h-[200rpx] leading-[200rpx] text-center " style="background-color: rgba(0,0,0,0.3);">
|
|
||||||
<text class="text-[#fff] text-[28rpx]">已失效</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-wrap ml-[20rpx]">
|
|
||||||
<view class="w-[100%] flex flex-col items-baseline">
|
|
||||||
<view class="text-[#333] text-[28rpx] max-h-[80rpx] leading-[40rpx] font-400 multi-hidden">
|
|
||||||
{{ item.goods.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view class="box-border max-w-[376rpx] mt-[10rpx] px-[14rpx] h-[36rpx] leading-[36rpx] truncate text-[var(--text-color-light6)] bg-[#F5F5F5] text-[22rpx] rounded-[20rpx]" v-if="item.goodsSku && item.goodsSku.sku_spec_format">
|
|
||||||
{{ item.goodsSku.sku_spec_format }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-end self-end w-[100%]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500">{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<ns-goods-recommend></ns-goods-recommend>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 优惠明细 -->
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup class="popup-type" :show="couponDetailsShow" @close="couponDetailsShow = false">
|
|
||||||
<view class="min-h-[200rpx] popup-common" @touchmove.prevent.stop>
|
|
||||||
<view class="flex justify-center items-center pt-[36rpx] pb-[56rpx] px-[26rpx] bg-[#fff] relative">
|
|
||||||
<text class="text-[32rpx]">优惠明细</text>
|
|
||||||
<text class="nc-iconfont nc-icon-guanbiV6xx text-[var(--text-color-light6)] absolute text-[32rpx] right-[26rpx]" @click="couponDetailsShow = false"></text>
|
|
||||||
</view>
|
|
||||||
<scroll-view class="h-[360rpx]" scroll-y="true">
|
|
||||||
<view class="flex justify-between h-[60rpx] px-[var(--pad-sidebar-m)]">
|
|
||||||
<text class="text-[28rpx]">商品总额</text>
|
|
||||||
<text class="text-[28rpx]">¥{{total.goods_money}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between h-[60rpx] px-[var(--pad-sidebar-m)]" v-if="Number(total.promotion_money)">
|
|
||||||
<text class="text-[28rpx]">满减</text>
|
|
||||||
<text class="text-[28rpx] text-[red]">-¥{{total.promotion_money}}</text>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view v-if="cartList.length" class="flex h-[96rpx] items-center bg-[#fff] fixed z-99999 left-0 right-0 bottom-[50px] pl-[30rpx] pr-[20rpx] box-solid mb-ios justify-between border-0 border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center" @click="selectAll">
|
|
||||||
<text class="self-center iconfont text-color text-[34rpx] mr-[10rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0" :class="cartList.length == checkedNum ? 'iconxuanze1' : 'bg-[#F5F5F5]'"></text>
|
|
||||||
<text class="font-400 text-[#303133] text-[26rpx]">全选</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="flex-1 flex items-center justify-between" v-if="!isEdit">
|
|
||||||
<view class="mr-[20rpx]">
|
|
||||||
<view class="flex items-center text-[var(--price-text-color)] leading-[45rpx]">
|
|
||||||
<view class="font-400 text-[#303133] text-[28rpx]">合计:</view>
|
|
||||||
<text class="text-[var(--price-text-color)] price-font text-[32rpx] font-bold">
|
|
||||||
¥{{ parseFloat(total.order_money).toFixed(2) }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-end mt-[6rpx]" v-if="Number(total.promotion_money)" @click="couponDetailsShow = true">
|
|
||||||
<text class="text-[22rpx] text-[#666]">优惠明细</text>
|
|
||||||
<text class="iconfont iconjiantoushang text-[#666] !text-[22rpx] ml-[4rpx] font-bold"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="settlement">结算</button>
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 flex items-center justify-end" v-else>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="deleteCartFn">删除</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifndef H5 -->
|
|
||||||
<view v-if="cartList.length" class="pl-[30rpx] pr-[20rpx] flex h-[96rpx] items-center bg-[#fff] fixed z-99999 left-0 right-0 bottom-[100rpx] box-solid mb-ios justify-between border-0 border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center" @click="selectAll">
|
|
||||||
<text class="self-center iconfont text-color text-[30rpx] mr-[20rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0" :class="{'iconxuanze1' :cartList.length == checkedNum, 'bg-[#F5F5F5]':cartList.length != checkedNum}"></text>
|
|
||||||
<text class="font-400 text-[#303133] text-[26rpx]">全选</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="flex-1 flex items-center justify-between" v-if="!isEdit">
|
|
||||||
<view class="mr-[20rpx]">
|
|
||||||
<view class="flex items-center text-[var(--price-text-color)] leading-[45rpx]">
|
|
||||||
<view class="font-400 text-[#303133] text-[28rpx]">合计:</view>
|
|
||||||
<text class="text-[var(--price-text-color)] price-font text-[32rpx] font-bold">
|
|
||||||
¥{{ parseFloat(total.order_money).toFixed(2) }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-end mt-[6rpx]" v-if="total.promotion_money" @click="couponDetailsShow = true">
|
|
||||||
<text class="text-[22rpx] text-[#666]">优惠明细</text>
|
|
||||||
<text class="iconfont iconjiantoushang text-[#666] !text-[22rpx] ml-[4rpx] font-bold"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="settlement">结算</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<button v-if="isBindMobile && info && !info.mobile" class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">结算</button>
|
|
||||||
<button v-else class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="settlement">结算</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 flex items-center justify-end" v-else>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="deleteCartFn">删除</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
<ns-goods-manjian ref="manjianShowRef"></ns-goods-manjian>
|
|
||||||
<tabbar />
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, watch,nextTick } from 'vue'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
|
||||||
import { img, redirect, getToken } from '@/utils/common'
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
import { getCartGoodsList, getCartCalculate } from '@/addon/shop/api/cart'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
import {t} from "@/locale";
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
import nsGoodsManjian from '@/addon/shop/components/ns-goods-manjian/ns-goods-manjian.vue';
|
|
||||||
import nsGoodsRecommend from '@/addon/shop/components/ns-goods-recommend/ns-goods-recommend.vue';
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const info = computed(() => memberStore.info)
|
|
||||||
const loading = ref(true)
|
|
||||||
const optionLoading = ref(false)
|
|
||||||
const total = ref({
|
|
||||||
goods_money: 0, //商品金额
|
|
||||||
order_money: 0, //订单金额
|
|
||||||
promotion_money: 0 //优惠金额
|
|
||||||
})
|
|
||||||
const cartList = ref<object[]>([])
|
|
||||||
const invalidList = ref<object[]>([]) // 失效商品:已下架、已删除
|
|
||||||
const isEdit = ref(false)
|
|
||||||
const querOne = ref(true)
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
const manjianShowRef: any = ref(null); //满减送
|
|
||||||
const couponDetailsShow: any = ref(false); //优惠明细
|
|
||||||
|
|
||||||
const getCartGoodsListFn = () => {
|
|
||||||
getCartGoodsList({}).then(({ data }) => {
|
|
||||||
cartList.value = []
|
|
||||||
invalidList.value = []
|
|
||||||
data.forEach(item => {
|
|
||||||
item.checked = false
|
|
||||||
if (item.goodsSku) {
|
|
||||||
if (item.goods.status && item.goods.delete_time == 0) {
|
|
||||||
if (item.goodsSku.stock) {
|
|
||||||
if (item.num > item.goodsSku.stock) item.num = item.goodsSku.stock;
|
|
||||||
cartList.value.push(item)
|
|
||||||
} else {
|
|
||||||
// 库存为0 时,移动到售罄商品
|
|
||||||
invalidList.value.push(item)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
invalidList.value.push(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
selectAll();
|
|
||||||
cartCalculateFn();
|
|
||||||
loading.value = false
|
|
||||||
if (querOne.value) querOne.value = false
|
|
||||||
}).catch((err) => {
|
|
||||||
if (err.code == 401) {
|
|
||||||
cartList.value = []
|
|
||||||
invalidList.value = []
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
getCartGoodsListFn()
|
|
||||||
cartStore.getList();
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsSkuInputFn = (data)=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!data.num || data.num <= numLimit(data).min ){
|
|
||||||
data.num = numLimit(data).min;
|
|
||||||
}
|
|
||||||
if(data.num >= numLimit(data).max){
|
|
||||||
data.num = numLimit(data).max;
|
|
||||||
}
|
|
||||||
uni.$u.debounce((event: any) => {
|
|
||||||
cartStore.increase({
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
stock: data.goodsSku.stock,
|
|
||||||
sale_price: data.goodsSku.sale_price,
|
|
||||||
num: Number(data.num)
|
|
||||||
}, 0);
|
|
||||||
}, 500)
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
const goodsSkuBlurFn = (event, index)=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
const data: any = cartList.value[index]
|
|
||||||
if(!data.num || data.num <= numLimit(data).min ){
|
|
||||||
data.num = numLimit(data).min;
|
|
||||||
}
|
|
||||||
if(data.num >= numLimit(data).max){
|
|
||||||
data.num = numLimit(data).max;
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.$u.debounce((event: any) => {
|
|
||||||
cartStore.increase({
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
stock: data.goodsSku.stock,
|
|
||||||
sale_price: data.goodsSku.sale_price,
|
|
||||||
num: Number(data.num)
|
|
||||||
}, 0,cartCalculateFn());
|
|
||||||
}, 500)
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkedNum = computed(() => {
|
|
||||||
let num = 0
|
|
||||||
cartList.value.forEach((item: any) => {
|
|
||||||
item.checked && (num += 1)
|
|
||||||
})
|
|
||||||
return num
|
|
||||||
})
|
|
||||||
|
|
||||||
const manjianOpenFn = (data:any) =>{
|
|
||||||
let obj = {};
|
|
||||||
obj.condition_type = data.condition_type;
|
|
||||||
obj.rule_json = data.rule_json;
|
|
||||||
obj.name = data.manjian_name;
|
|
||||||
manjianShowRef.value.open(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
let isLoadCalculate = false;
|
|
||||||
const cartCalculateFn = () =>{
|
|
||||||
let calculateArr: Object = [];
|
|
||||||
cartList.value.forEach((item:any) => {
|
|
||||||
if (item.checked && item.goodsSku) {
|
|
||||||
let obj = {};
|
|
||||||
obj.num = item.num;
|
|
||||||
obj.sku_id = item.sku_id;
|
|
||||||
calculateArr.push(obj);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if(!calculateArr.length){
|
|
||||||
total.value.order_money = 0
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isLoadCalculate)return false;
|
|
||||||
isLoadCalculate = true;
|
|
||||||
|
|
||||||
getCartCalculate({sku_ids: calculateArr}).then(({ data }) => {
|
|
||||||
total.value.goods_money = data.goods_money;
|
|
||||||
total.value.order_money = data.order_money;
|
|
||||||
total.value.promotion_money = data.promotion_money;
|
|
||||||
cartList.value.forEach((item,index)=>{
|
|
||||||
for(let subIndex = 0; subIndex < data.match_list.length; subIndex++){
|
|
||||||
if(item.goods_id == data.match_list[subIndex].goods_id && item.sku_id == data.match_list[subIndex].sku_id && item.manjian_info && Object.keys(item.manjian_info).length){
|
|
||||||
item.manjian_info.is_show = true;
|
|
||||||
let subTempShowNum = 0;
|
|
||||||
item.manjian_info.rule_json.forEach((threeItem, threeIndex)=>{
|
|
||||||
if(threeIndex == data.match_list[subIndex].level){
|
|
||||||
threeItem.is_show = true;
|
|
||||||
subTempShowNum++;
|
|
||||||
}else{
|
|
||||||
threeItem.is_show = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(subTempShowNum == 0){
|
|
||||||
item.manjian_info.is_show = false;
|
|
||||||
}else{
|
|
||||||
item.manjian_info.is_show = true;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(item.manjian_info && Object.keys(item.manjian_info).length){
|
|
||||||
item.manjian_info.is_show = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
isLoadCalculate = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLogin = () => {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/goods/cart' })
|
|
||||||
}
|
|
||||||
|
|
||||||
const toDetail = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
const numChange = (event: any, index: any) => {
|
|
||||||
uni.$u.debounce((event: any) => {
|
|
||||||
const data: any = cartList.value[index]
|
|
||||||
cartStore.increase({
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
stock: data.goodsSku.stock,
|
|
||||||
sale_price: data.goodsSku.sale_price,
|
|
||||||
num: data.num
|
|
||||||
}, 0, cartCalculateFn());
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
const addNumChange = (data: any) => {
|
|
||||||
if(data.num >= data.goods.stock){
|
|
||||||
uni.showToast({ title: "商品库存不足", icon: 'none' });
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data.goods.is_limit){
|
|
||||||
let tips = `该商品单次限购${data.goods.max_buy}件`;
|
|
||||||
if(data.goods.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${data.goods.max_buy}件`;
|
|
||||||
}
|
|
||||||
if(data.num >= data.goods.max_buy){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reduceNumChange = (data: any) => {
|
|
||||||
if(data.goods.is_limit && data.goods.min_buy){
|
|
||||||
let tips = `该商品起购${data.goods.min_buy}件`;
|
|
||||||
if(data.num <= data.goods.min_buy){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const numLimit = (data: any) => {
|
|
||||||
let obj = {
|
|
||||||
min: 1,
|
|
||||||
max: data.goodsSku.stock || 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(data.goods.is_limit){
|
|
||||||
if(data.goods.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
max_buy = data.goods.max_buy;
|
|
||||||
|
|
||||||
if(max_buy > data.goods.stock){
|
|
||||||
obj.max = data.goods.stock
|
|
||||||
}else if(max_buy <= data.goods.stock){
|
|
||||||
obj.max = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起售
|
|
||||||
if(data.goods.min_buy > 0){
|
|
||||||
obj.min = data.goods.min_buy;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cartOptions = ref([
|
|
||||||
{
|
|
||||||
text: t('delete'),
|
|
||||||
style: {
|
|
||||||
backgroundColor: '#EF000C',
|
|
||||||
width: '100rpx',
|
|
||||||
height:'100%',
|
|
||||||
borderRadius: '10rpx'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
const swipeActive = ref()
|
|
||||||
const swipeClick = (index:any,item:any) => {
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
cartStore.delete(item.id, () => {
|
|
||||||
cartList.value.splice(index, 1)
|
|
||||||
nextTick(()=>{if(swipeActive.value)swipeActive.value.closeOther() })
|
|
||||||
cartCalculateFn();
|
|
||||||
optionLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 选择单个商品
|
|
||||||
*/
|
|
||||||
const selectOnlyGoods = (data:any = {}) => {
|
|
||||||
data.checked = !data.checked
|
|
||||||
cartCalculateFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全选
|
|
||||||
*/
|
|
||||||
const selectAll = () => {
|
|
||||||
const checked = cartList.value.length == checkedNum.value ? false : true
|
|
||||||
cartList.value.forEach((item: any) => {
|
|
||||||
item.checked = checked
|
|
||||||
})
|
|
||||||
cartCalculateFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const isBindMobile = ref(uni.getStorageSync('isbindmobile'))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 结算
|
|
||||||
*/
|
|
||||||
const settlement = () => {
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
if(uni.getStorageSync('isbindmobile')){
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
if (!checkedNum.value) {
|
|
||||||
uni.showToast({ title: '还没有选择商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const ids: any = []
|
|
||||||
cartList.value.forEach((item: any) => {
|
|
||||||
if (item.checked) ids.push(item.id)
|
|
||||||
})
|
|
||||||
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'orderCreateData',
|
|
||||||
data: {
|
|
||||||
cart_ids: ids
|
|
||||||
},
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/payment' })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除
|
|
||||||
*/
|
|
||||||
const deleteCartFn = () => {
|
|
||||||
if (!checkedNum.value) {
|
|
||||||
uni.showToast({ title: '还没有选择商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
|
|
||||||
const ids: any = []
|
|
||||||
cartList.value.forEach((item: any) => {
|
|
||||||
if (item.checked) ids.push(item.id)
|
|
||||||
})
|
|
||||||
|
|
||||||
cartStore.delete(ids, () => {
|
|
||||||
getCartGoodsListFn()
|
|
||||||
optionLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 清空无效商品
|
|
||||||
*/
|
|
||||||
const deleteInvalidList = ()=>{
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
const ids = invalidList.value.map((el: any)=>el.id)
|
|
||||||
|
|
||||||
cartStore.delete(ids, () => {
|
|
||||||
getCartGoodsListFn()
|
|
||||||
optionLoading.value = false
|
|
||||||
})
|
|
||||||
invalidList.value = []
|
|
||||||
}
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = (data:any) => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (data.goods.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
price = data.goodsSku.member_price ? data.goodsSku.member_price : data.goodsSku.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = data.goodsSku.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(uni-page) {
|
|
||||||
background: var(--page-bg-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
uni-page-body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-bar-placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar__placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.scroll-height {
|
|
||||||
height: calc(100vh - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.scroll-height {
|
|
||||||
height: calc(100vh - 200rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 200rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
.text-ellipsis{
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right){
|
|
||||||
padding: 2rpx;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right__button__wrapper){
|
|
||||||
padding:0 10rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right__button__wrapper__text){
|
|
||||||
font-size:24rpx !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar .u-tabbar__content){
|
|
||||||
z-index: 99999 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<category-template-one-one class="category" v-if="config.level===1 && config.template === 'style-1'" :categoryId="categoryId" :config="config" />
|
|
||||||
<category-template-two-one v-if="config.level===2 && config.template === 'style-1'" :categoryId="categoryId" :config="config" />
|
|
||||||
<category-template-two-two class="category" v-if="config.level===2 && config.template === 'style-2'" :categoryId="categoryId" :config="config" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import categoryTemplateTwoOne from '@/addon/shop/pages/goods/components/category-template-two-one.vue';
|
|
||||||
import categoryTemplateOneOne from '@/addon/shop/pages/goods/components/category-template-one-one.vue';
|
|
||||||
import categoryTemplateTwoTwo from '@/addon/shop/pages/goods/components/category-template-two-two.vue';
|
|
||||||
import { getGoodsCategoryConfig } from '@/addon/shop/api/goods';
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
const config: any = ref({})
|
|
||||||
const categoryId = ref(0)
|
|
||||||
|
|
||||||
const getGoodsCategoryConfigFn = () => {
|
|
||||||
getGoodsCategoryConfig().then(res => {
|
|
||||||
config.value = res.data
|
|
||||||
uni.setNavigationBarTitle({
|
|
||||||
title: config.value.page_title
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad((options:any) => {
|
|
||||||
categoryId.value = options.category_id || 0;
|
|
||||||
getGoodsCategoryConfigFn()
|
|
||||||
});
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
// 查询购物车列表
|
|
||||||
cartStore.getList();
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
|
|
||||||
/* #ifdef H5 */
|
|
||||||
:deep(.category .detail .mescroll-body) {
|
|
||||||
padding-bottom: calc(50px + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(50px + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.category .cart .mescroll-body){
|
|
||||||
padding-bottom: calc(100rpx + 50px + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(100rpx + 50px + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.category .detail .mescroll-body {
|
|
||||||
padding-bottom: calc(100rpx + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(100rpx + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category .cart .mescroll-body {
|
|
||||||
padding-bottom: calc(200rpx + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(200rpx + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
.category .labelPopup :deep(.u-fade-enter-active) {
|
|
||||||
top: 92rpx !important;
|
|
||||||
left: 166rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.category .labelPopup :deep(.u-slide-down-enter-active){
|
|
||||||
top: 92rpx !important;
|
|
||||||
left: 165rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
}
|
|
||||||
.category .labelPopup.active :deep(.u-fade-enter-active) {
|
|
||||||
top: 190rpx !important;
|
|
||||||
|
|
||||||
}
|
|
||||||
.category .labelPopup.active :deep(.u-slide-down-enter-active){
|
|
||||||
top: 190rpx !important;
|
|
||||||
}
|
|
||||||
.category .labelPopup :deep(.u-fade-enter-to){
|
|
||||||
top: 92rpx !important;
|
|
||||||
left: 166rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
}
|
|
||||||
.category .labelPopup :deep(.u-slide-down-leave-to){
|
|
||||||
top: 92rpx !important;
|
|
||||||
left: 165rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
} */
|
|
||||||
.category .labelPopup :deep(.u-transition) {
|
|
||||||
top: 96rpx !important;
|
|
||||||
left: 170rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
&:nth-child(2){
|
|
||||||
left: 168rpx !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.category .labelPopup.active :deep(.u-transition) {
|
|
||||||
top: 190rpx !important;
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
:deep(.mescroll-upwarp) {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-left: 182rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-bar-placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar__placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
button::after{
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.part .mescroll-empty){
|
|
||||||
width: 542rpx;
|
|
||||||
height: 542rpx;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
padding-top: 50rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-page min-h-screen overflow-hidden ">
|
|
||||||
<mescroll-body ref="mescrollRef" top="0" @init="mescrollInit" :down="{ use: false }" @up="getCollectListFn">
|
|
||||||
<view class="py-[var(--top-m)] sidebar-margin" v-if="goodsList.length">
|
|
||||||
<view class="bg-[#fff] pb-[10rpx] box-border rounded-[var(--rounded-big)]" >
|
|
||||||
<view class="flex mx-[var(--rounded-big)] pt-[var(--pad-top-m)] justify-between items-center box-border font-400 text-[24rpx] mb-[24rpx] leading-[30rpx]">
|
|
||||||
<view class="flex items-baseline text-[24rpx] text-[#333]">
|
|
||||||
<text>共</text>
|
|
||||||
<text class="text-[32rpx] mx-[2rpx] text-[var(--price-text-color)]">{{ goodsList.length }}</text>
|
|
||||||
<text>件商品</text>
|
|
||||||
</view>
|
|
||||||
<text @click="isEdit = !isEdit" class="text-[var(--text-color-light6)] text-[24rpx]">{{ isEdit ? '完成' : '管理' }}</text>
|
|
||||||
</view>
|
|
||||||
<u-swipe-action ref="swipeActive">
|
|
||||||
<block v-for="(item, index) in goodsList" :key="index">
|
|
||||||
<view class="py-[20rpx] overflow-hidden w-full">
|
|
||||||
<u-swipe-action-item :options="cartOptions" @click="swipeClick(item)">
|
|
||||||
<view class="flex px-[var(--pad-sidebar-m)]">
|
|
||||||
<view class="self-center w-[58rpx] h-[60rpx] flex items-center" v-if="isEdit" @click.stop="item.checked = !item.checked">
|
|
||||||
<text class=" iconfont text-primary text-[34rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden shrink-0"
|
|
||||||
:class="{ 'iconxuanze1':item.checked,'bg-[#F5F5F5]':!item.checked}">
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1" @click="toDetail(item)">
|
|
||||||
<view class="relative w-[200rpx] h-[200rpx] flex items-center justify-center rounded-[var(--goods-rounded-big)] overflow-hidden">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="200rpx" height="200rpx" :src="img(item.goods_cover_thumb_mid||'')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[200rpx] h-[200rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view v-if="item.status == 0 " class="absolute left-0 top-0 w-[200rpx] h-[200rpx] leading-[200rpx] text-center " style="background-color: rgba(0,0,0,0.3);">
|
|
||||||
<text class="text-[#fff] text-[28rpx]">已失效</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-wrap ml-[20rpx]">
|
|
||||||
<view class="w-[100%] flex flex-col items-baseline">
|
|
||||||
<view class="text-[#333] text-[28rpx] max-h-[80rpx] leading-[40rpx] multi-hidden font-400">
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view class="box-border max-w-[376rpx] mt-[10rpx] px-[14rpx] h-[36rpx] leading-[36rpx] truncate text-[var(--text-color-light6)] bg-[#F5F5F5] text-[22rpx] rounded-[20rpx]" v-if="item.sku_name">
|
|
||||||
{{ item.sku_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-end self-end mt-[10rpx] w-[100%]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font truncate max-w-[200rpx]">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(item.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(item.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-swipe-action-item>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</u-swipe-action>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!goodsList.length && loading" :option="{tip : '暂无收藏的商品'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<view v-if="goodsList.length && isEdit" class="flex h-[96rpx] items-center bg-[#fff] fixed left-0 right-0 bottom-0 pl-[30rpx] pr-[20rpx] box-solid mb-ios justify-between">
|
|
||||||
<view class="flex items-center" @click="selectAll">
|
|
||||||
<text class="self-center iconfont text-primary text-[34rpx] mr-[10rpx] w-[34rpx] h-[34rpx] rounded-[17rpx] overflow-hidden flex-shrink-0" :class="{'iconxuanze1': goodsList.length == checkedNum, 'bg-color': goodsList.length != checkedNum }"></text>
|
|
||||||
<text class="font-400 text-[#303133] text-[26rpx]">全选</text>
|
|
||||||
</view>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" @click="deleteCollectFn">取消收藏</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed,} from 'vue'
|
|
||||||
import {t} from "@/locale";
|
|
||||||
import { img, redirect } from '@/utils/common'
|
|
||||||
import { getCollectList, cancelCollect } from '@/addon/shop/api/goods';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const optionLoading = ref(false)
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
const isEdit = ref(false)
|
|
||||||
|
|
||||||
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCollectListFn = (mescroll: mescrollStructure) => {
|
|
||||||
loading.value = false
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size
|
|
||||||
};
|
|
||||||
getCollectList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (Number(mescroll.num) === 1) {
|
|
||||||
goodsList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
newArr = newArr.map((item: any) =>{
|
|
||||||
item.checked = false
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
goodsList.value = goodsList.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const cartOptions = ref([
|
|
||||||
{
|
|
||||||
text: t('delete'),
|
|
||||||
style: {
|
|
||||||
backgroundColor: '#EF000C',
|
|
||||||
width: '100rpx',
|
|
||||||
height:'100%',
|
|
||||||
borderRadius: '10rpx'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 取消单个收藏
|
|
||||||
const swipeClick = (data: any) => {
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
cancelCollect({goods_ids: [data.goods_id]}).then((res: any) => {
|
|
||||||
optionLoading.value = false
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//取消全部收藏
|
|
||||||
const deleteCollectFn = () => {
|
|
||||||
if (!checkedNum.value) {
|
|
||||||
uni.showToast({ title: '请先选择收藏的商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (optionLoading.value) return
|
|
||||||
optionLoading.value = true
|
|
||||||
const ids: any = []
|
|
||||||
goodsList.value.forEach((item: any) => {
|
|
||||||
if (item.checked) ids.push(item.goods_id)
|
|
||||||
})
|
|
||||||
cancelCollect({goods_ids: ids}).then((res: any) => {
|
|
||||||
optionLoading.value = false
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 选中数量
|
|
||||||
const checkedNum = computed(() => {
|
|
||||||
let num = 0
|
|
||||||
goodsList.value.forEach((item: any) => {
|
|
||||||
item.checked && (num += 1)
|
|
||||||
})
|
|
||||||
return num
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全选
|
|
||||||
*/
|
|
||||||
const selectAll = () => {
|
|
||||||
const checked = goodsList.value.length == checkedNum.value ? false : true
|
|
||||||
goodsList.value.forEach((item: any) => {
|
|
||||||
item.checked = checked
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const toDetail = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: data.goods_id } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.bg-color{
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right){
|
|
||||||
padding: 2rpx;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right__button__wrapper){
|
|
||||||
padding:0 10rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-swipe-action-item__right__button__wrapper__text){
|
|
||||||
font-size:24rpx !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,374 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup :show="goodsSkuPop" @close="closeFn" mode="bottom">
|
|
||||||
<view v-if="Object.keys(goodsDetail).length" @touchmove.prevent.stop class="rounded-t-[20rpx] overflow-hidden bg-[#fff] py-[32rpx] relative">
|
|
||||||
<view class="flex px-[32rpx] mb-[58rpx]">
|
|
||||||
<u--image width="180rpx" height="180rpx" :radius="'var(--goods-rounded-big)'" :src="img(detail.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[180rpx] h-[180rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
|
|
||||||
<view class="flex flex-1 flex-col justify-between ml-[20rpx] py-[10rpx]">
|
|
||||||
<view class="w-[100%]">
|
|
||||||
<view class=" text-[var(--price-text-color)] flex items-baseline">
|
|
||||||
<text class="text-[32rpx] font-bold price-font mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[48rpx] price-font">{{ parseFloat(goodsPrice(detail)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[32rpx] price-font">.{{ parseFloat(goodsPrice(detail)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
<image class="h-[24rpx] ml-[6rpx] max-w-[44rpx]" v-if="priceType(detail) == 'member_price'" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[32rpx] text-[#303133] mt-[12rpx]">库存{{ detail.stock }}{{ goodsDetail.goods.unit }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[100%] text-[26rpx] leading-[30rpx] text-[var(--text-color-light6)] multi-hidden max-h-[60rpx]" v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length">已选规格:{{ detail.sku_spec_format }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view class="h-[500rpx] box-border px-[32rpx] mb-[30rpx]" scroll-y="true">
|
|
||||||
<view :class="{'mt-[36rpx]': 0 != index }" v-for="(item, index) in goodsDetail.goodsSpec" :key="index">
|
|
||||||
<view class="text-[26rpx] leading-[36rpx] mb-[24rpx]">{{ item.spec_name }}</view>
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<view
|
|
||||||
class="box-border bg-[#f2f2f2] text-[24rpx] px-[44rpx] text-center h-[56rpx] leading-[52rpx] mr-[20rpx] mb-[20rpx] border-1 border-solid rounded-[50rpx] border-[#f2f2f2]"
|
|
||||||
:class="{'!border-[var(--primary-color)] text-[var(--primary-color)] !bg-[var(--primary-color-light)]': subItem.selected}"
|
|
||||||
v-for="(subItem, subIndex) in item.values" :key="subIndex" @click="change(subItem, index)">
|
|
||||||
{{ subItem.name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-center mt-[8rpx]">
|
|
||||||
<view class="text-[26rpx]">购买数量</view>
|
|
||||||
<text v-if="maxBuyShow > 0 && minBuyShow > 1" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">
|
|
||||||
({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售,限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})
|
|
||||||
</text>
|
|
||||||
<text v-else-if="maxBuyShow > 0" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">(限购{{ maxBuyShow }}{{ goodsDetail.goods.unit }})</text>
|
|
||||||
<text v-else-if="minBuyShow > 1" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">({{ minBuyShow }}{{ goodsDetail.goods.unit }}起售)</text>
|
|
||||||
<u-number-box
|
|
||||||
v-if="cartList['goods_' + detail.goods_id] && cartList['goods_' + detail.goods_id]['sku_' + detail.sku_id]"
|
|
||||||
v-model="buyNum" :min="minBuy" :max="maxBuy" integer :step="1" input-width="98rpx"
|
|
||||||
input-height="54rpx">
|
|
||||||
<template #minus>
|
|
||||||
<view class="relative w-[34rpx] h-[34rpx]" @click="reduceNumChange()">
|
|
||||||
<text class="text-[34rpx] nc-iconfont nc-icon-jianV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum <= minBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template #input>
|
|
||||||
<input class="text-[#303133] text-[28rpx] mx-[10rpx] w-[80rpx] h-[44rpx] bg-[var(--temp-bg)] leading-[44rpx] text-center rounded-[6rpx]" type="number" @input="goodsSkuInputFn" @blur="goodsSkuBlurFn" v-model="buyNum" />
|
|
||||||
</template>
|
|
||||||
<template #plus>
|
|
||||||
<view class="relative w-[34rpx] h-[34rpx]" @click="addNumChange()">
|
|
||||||
<text class="text-[34rpx] nc-iconfont nc-icon-jiahaoV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum >= maxBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</u-number-box>
|
|
||||||
<u-number-box v-else v-model="buyNum" :min="minBuy" :max="maxBuy" integer :step="1" input-width="98rpx" input-height="54rpx">
|
|
||||||
<template #minus>
|
|
||||||
<view class="relative w-[34rpx] h-[34rpx]" @click="reduceNumChange()">
|
|
||||||
<text class="text-[34rpx] nc-iconfont nc-icon-jianV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum <= minBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template #input>
|
|
||||||
<input class="text-[#303133] text-[28rpx] mx-[10rpx] w-[80rpx] h-[44rpx] bg-[var(--temp-bg)] leading-[44rpx] text-center rounded-[6rpx]" type="number" @input="goodsSkuInputFn" @blur="goodsSkuBlurFn" v-model="buyNum" />
|
|
||||||
</template>
|
|
||||||
<template #plus>
|
|
||||||
<view class="relative w-[34rpx] h-[34rpx]" @click="addNumChange()">
|
|
||||||
<text class="text-[34rpx] nc-iconfont nc-icon-jiahaoV6xx font-500 absolute flex items-center justify-center -left-[8rpx] -bottom-[8rpx] -right-[8rpx] -top-[8rpx]" :class="{ '!text-[var(--text-color-light9)]': buyNum >= maxBuy }"></text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</u-number-box>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="px-[20rpx]">
|
|
||||||
<button v-if="detail.stock > 0" class="!h-[80rpx] font-500 primary-btn-bg leading-[80rpx] text-[26rpx] rounded-[50rpx]" type="primary" @click="save">确定</button>
|
|
||||||
<button v-else class="!h-[80rpx] leading-[80rpx] font-500 text-[26rpx] text-[#fff] bg-[#ccc] rounded-[50rpx]">已售罄</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, computed, watch, toRaw } from 'vue';
|
|
||||||
import { img, redirect, getToken } from '@/utils/common';
|
|
||||||
import { getGoodsSku } from '@/addon/shop/api/goods';
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
const cartList = computed(() => cartStore.cartList)
|
|
||||||
|
|
||||||
const goodsSkuPop = ref(false);
|
|
||||||
const currSpec: any = ref({
|
|
||||||
skuId: "",
|
|
||||||
name: []
|
|
||||||
})
|
|
||||||
const info: any = ref({})//获取原始数据
|
|
||||||
const detail:any = ref({})//展示数据
|
|
||||||
const buyNum = ref(1)
|
|
||||||
|
|
||||||
const maxBuy = ref(0); // 限购
|
|
||||||
const minBuy = ref(0); // 起售
|
|
||||||
const maxBuyShow = ref(0); // 限购,只展示
|
|
||||||
const minBuyShow = ref(0); // 起售,只展示
|
|
||||||
|
|
||||||
const getGoodsSkuFn = (sku_id: any) => {
|
|
||||||
getGoodsSku(sku_id).then((res: any) => {
|
|
||||||
info.value = res.data
|
|
||||||
// 当前详情内容
|
|
||||||
currSpec.value.sku_id = sku_id
|
|
||||||
if (info.value.skuList && Object.keys(info.value.skuList).length) {
|
|
||||||
info.value.skuList.forEach((item: any) => {
|
|
||||||
if (item.sku_id == sku_id) {
|
|
||||||
detail.value = item;
|
|
||||||
currSpec.value.name = item.sku_spec_format.split(",");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
goodsSkuPop.value = true;
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsSkuInputFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= minBuy.value ){
|
|
||||||
buyNum.value = minBuy.value || 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= maxBuy.value){
|
|
||||||
buyNum.value = maxBuy.value;
|
|
||||||
}
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > buyNum.value){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
const goodsSkuBlurFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= minBuy.value ){
|
|
||||||
buyNum.value = minBuy.value || 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= maxBuy.value){
|
|
||||||
buyNum.value = maxBuy.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > buyNum.value){
|
|
||||||
buyNum.value = 0;
|
|
||||||
uni.showToast({
|
|
||||||
title: '库存数量小于起购数量',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const open = (sku_id: any) => {
|
|
||||||
getGoodsSkuFn(sku_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeFn = () => {
|
|
||||||
goodsSkuPop.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsDetail = computed(() => {
|
|
||||||
let data = cloneDeep(info.value);
|
|
||||||
|
|
||||||
// 重组数据结构
|
|
||||||
if (Object.keys(data).length) {
|
|
||||||
|
|
||||||
if (!Object.keys(currSpec.value.name).length) currSpec.value.name = data.sku_spec_format.split(",");
|
|
||||||
|
|
||||||
data.goodsSpec.forEach((item: any, index: any) => {
|
|
||||||
let specName = item.spec_values.split(",");
|
|
||||||
item.values = [];
|
|
||||||
specName.forEach((specItem: any, specIndex: any) => {
|
|
||||||
item.values[specIndex] = {};
|
|
||||||
item.values[specIndex].name = specItem;
|
|
||||||
item.values[specIndex].selected = false;
|
|
||||||
item.values[specIndex].disabled = false;
|
|
||||||
|
|
||||||
// 选中规格
|
|
||||||
currSpec.value.name.forEach((currSpecItem: any, currSpecIndex: any) => {
|
|
||||||
if (currSpecIndex == index && currSpecItem == specItem) {
|
|
||||||
item.values[specIndex].selected = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
getSkuId();
|
|
||||||
|
|
||||||
// 当前详情内容
|
|
||||||
if (data.skuList && Object.keys(data.skuList).length) {
|
|
||||||
data.skuList.forEach((item: any) => {
|
|
||||||
if (item.sku_id == currSpec.value.skuId) {
|
|
||||||
detail.value = item;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/************************** 限购-start **************************/
|
|
||||||
maxBuy.value = detail.value.stock
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(data.goods.is_limit){
|
|
||||||
if(data.goods && data.goods.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(data.goods.limit_type == 1){ //单次限购
|
|
||||||
max_buy = data.goods.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = data.goods.max_buy - (data.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(max_buy > detail.value.stock){
|
|
||||||
maxBuy.value = detail.value.stock
|
|
||||||
}else if(max_buy <= detail.value.stock){
|
|
||||||
maxBuy.value = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 仅用于展示
|
|
||||||
maxBuyShow.value = data.goods.max_buy; // 限购
|
|
||||||
// 限购开启且最大购买变为零时,初始值也应该是零
|
|
||||||
if(maxBuy.value == 0){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 起售
|
|
||||||
minBuy.value = data.goods.min_buy;
|
|
||||||
buyNum.value = minBuy.value > 0 ? data.goods.min_buy : 1;
|
|
||||||
// 仅用于展示
|
|
||||||
minBuyShow.value = data.goods.min_buy;
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
if(minBuy.value > detail.value.stock){
|
|
||||||
buyNum.value = 0;
|
|
||||||
}
|
|
||||||
/************************** 限购-end **************************/
|
|
||||||
return data;
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => detail.value,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if (cartList.value['goods_' + detail.value.goods_id] && cartList.value['goods_' + detail.value.goods_id]['sku_' + detail.value.sku_id]) {
|
|
||||||
buyNum.value = toRaw(cartList.value['goods_' + detail.value.goods_id]['sku_' + detail.value.sku_id].num);
|
|
||||||
detail.value.cart_id = toRaw(cartList.value['goods_' + detail.value.goods_id]['sku_' + detail.value.sku_id].id)
|
|
||||||
} else {
|
|
||||||
// 起售大于库存,初始值也应该是零
|
|
||||||
let num = 1;
|
|
||||||
if(minBuy.value > 0){ num = minBuy.value; }
|
|
||||||
if(minBuy.value > detail.value.stock){ num = 0; }
|
|
||||||
buyNum.value = num;
|
|
||||||
detail.value.cart_id = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const change = (data: any, index: any) => {
|
|
||||||
currSpec.value.name[index] = data.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSkuId = () => {
|
|
||||||
info.value.skuList.forEach((skuItem: any, skuIndex: any) => {
|
|
||||||
let sku_spec_format = skuItem.sku_spec_format.split(',')
|
|
||||||
if (currSpec.value.name.every((v: any) => sku_spec_format.includes(v))) {
|
|
||||||
currSpec.value.skuId = skuItem.sku_id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const addNumChange = () => {
|
|
||||||
if(minBuy.value && minBuy.value > detail.value.stock){
|
|
||||||
uni.showToast({ title: '商品库存小于起购数量', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(goodsDetail.value.goods.is_limit){
|
|
||||||
let tips = `该商品单次限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
if(goodsDetail.value.goods.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${goodsDetail.value.goods.max_buy}件`;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= goodsDetail.value.goods.max_buy){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reduceNumChange = () => {
|
|
||||||
if(goodsDetail.value.goods.is_limit && minBuy.value){
|
|
||||||
let tips = `该商品起购${minBuy.value}件`;
|
|
||||||
if(buyNum.value <= minBuy.value){
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const save = () => {
|
|
||||||
//删除商品
|
|
||||||
if (buyNum.value == 0) {
|
|
||||||
// 购物车减少数量
|
|
||||||
cartStore.reduce({
|
|
||||||
id: detail.value.cart_id || '',
|
|
||||||
goods_id: detail.value.goods_id,
|
|
||||||
sale_price: detail.value.sale_price,
|
|
||||||
sku_id: detail.value.sku_id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
|
|
||||||
let price = 0
|
|
||||||
|
|
||||||
if (goodsDetail.value.goods.member_discount && getToken() && detail.value.member_price != detail.value.price) {
|
|
||||||
price = detail.value.member_price ? detail.value.member_price : detail.value.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = detail.value.price
|
|
||||||
}
|
|
||||||
|
|
||||||
// 购物车添加数量
|
|
||||||
cartStore.increase({
|
|
||||||
id: detail.value.cart_id || '',
|
|
||||||
goods_id: detail.value.goods_id,
|
|
||||||
sku_id: detail.value.sku_id,
|
|
||||||
stock: detail.value.stock,
|
|
||||||
sale_price: price,
|
|
||||||
num: buyNum.value
|
|
||||||
|
|
||||||
}, 0, () => {
|
|
||||||
uni.showToast({
|
|
||||||
title: '加入购物车成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
goodsSkuPop.value = false
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = (data:any) => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (goodsDetail.value.goods.member_discount && getToken() && data.member_price != data.price) {
|
|
||||||
price = data.member_price ? data.member_price : data.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = data.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 价格类型
|
|
||||||
const priceType = (data:any) => {
|
|
||||||
let type = "";
|
|
||||||
if (goodsDetail.value.goods.member_discount && getToken() && data.member_price != data.price) {
|
|
||||||
type = 'member_price' // 会员价
|
|
||||||
} else {
|
|
||||||
type = ""
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
::v-deep .u-number-box .u-number-box__slot{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,793 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="min-h-screen bg-[var(--page-bg-color)] overflow-hidden">
|
|
||||||
<view class="mescroll-box bg-[var(--page-bg-color)]" :class="{ 'cart': config.cart.control && config.cart.event === 'cart', 'detail': !(config.cart.control && config.cart.event === 'cart') }" v-if="tabsData.length">
|
|
||||||
<mescroll-body ref="mescrollRef" :down="{ use: false }" @init="mescrollInit" @up="getListFn">
|
|
||||||
<view v-if="config.search.control" class="search-box z-10 bg-[#fff] fixed top-0 left-0 right-0 h-[100rpx] box-border">
|
|
||||||
<view class="flex-1 search-input">
|
|
||||||
<text @click.stop="searchNameFn" class="nc-iconfont nc-icon-sousuo-duanV6xx1 btn"></text>
|
|
||||||
<input class="input" type="text" v-model="searchName" :placeholder="config.search.title" @confirm="searchNameFn" placeholderClass="text-[var(--text-color-light9)]">
|
|
||||||
<text v-if="searchName" class="nc-iconfont nc-icon-cuohaoV6xx1 clear" @click="searchName=''"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view class="tabs-box z-2 fixed left-0 bg-[#fff] bottom-[50px] top-0" :class="{ '!top-[100rpx]': config.search.control, 'pb-[98rpx]': config.cart.control && config.cart.event === 'cart' }">
|
|
||||||
<scroll-view :scroll-y="true" class="scroll-height">
|
|
||||||
<view class="bg-[var(--temp-bg)]">
|
|
||||||
<view class="tab-item" :class="{ 'tab-item-active': index == tabActive,'rounded-br-[12rpx]':tabActive-1===index,'rounded-tr-[12rpx]':tabActive+1===index}" v-for="(item, index) in tabsData" :key="index" @click="firstLevelClick(index, item)">
|
|
||||||
<view class="text-box text-left leading-[1.3] break-words px-[16rpx]">
|
|
||||||
{{ item.category_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifndef H5 -->
|
|
||||||
<view class="tabs-box z-2 fixed left-0 bg-[#fff] pb-ios bottom-[100rpx] top-0" :class="{ 'top-[126rpx]': config.search.control, '!bottom-[198rpx]': config.cart.control && config.cart.event === 'cart' }">
|
|
||||||
<scroll-view :scroll-y="true" class="scroll-height">
|
|
||||||
<view class="bg-[var(--temp-bg)]">
|
|
||||||
<view class="tab-item" :class="{ 'tab-item-active': index == tabActive,'rounded-br-[12rpx]':tabActive-1===index,'rounded-tr-[12rpx]':tabActive+1===index}" v-for="(item, index) in tabsData" :key="index" @click="firstLevelClick(index, item)">
|
|
||||||
<view class="text-box text-left leading-[1.3] break-words px-[16rpx]">
|
|
||||||
{{ item.category_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="flex justify-center flex-wrap pl-[188rpx] pb-[20rpx]" :class="{ ' pt-[120rpx]': config.search.control, ' pt-[20rpx]': !(config.search.control) }">
|
|
||||||
<template v-for="(item, index) in list" :key="item.goods_id">
|
|
||||||
<view
|
|
||||||
class="box-border bg-white w-full flex mr-[20rpx] py-[24rpx] px-[20rpx] rounded-[var(--rounded-small)]"
|
|
||||||
:class="{ 'mt-[16rpx]': index }" @click.stop="toLink(item.goods_id)">
|
|
||||||
<view class="w-[168rpx] h-[168rpx] flex items-center justify-center rounded-[var(--goods-rounded-small)] overflow-hidden">
|
|
||||||
<u--image width="168rpx" height="168rpx" radius="var(--goods-rounded-small)" :src="img( item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[168rpx] h-[168rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 ml-[20rpx] flex-wrap flex-col">
|
|
||||||
<view class="max-h-[80rpx] text-[26rpx] leading-[40rpx] multi-hidden">
|
|
||||||
{{ item.goods_name }}</view>
|
|
||||||
<view class="flex-1 flex items-end justify-between">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font -mb-[8rpx]">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
<image class="h-[24rpx] max-w-[46rpx] ml-[6rpx]" v-if="priceType(item) == 'member_price'" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<block v-if="!item.isMaxBuy">
|
|
||||||
<view
|
|
||||||
v-if="
|
|
||||||
(item.goods_type == 'real' || (item.goods_type == 'virtual' && item.virtual_receive_type != 'verify')) &&
|
|
||||||
item.goodsSku.sku_spec_format === '' && cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id] && config.cart.control && config.cart.event === 'cart'"
|
|
||||||
class="flex items-center">
|
|
||||||
<view class="relative w-[32rpx] h-[32rpx]">
|
|
||||||
<text class="text-[32rpx] text-color nc-iconfont nc-icon-jianshaoV6xx absolute flex items-center justify-center -left-[14rpx] -bottom-[14rpx] -right-[14rpx] -top-[14rpx]"
|
|
||||||
@click.stop="reduceCart(item, cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id])"></text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[#333] text-[24rpx] mx-[16rpx]">{{ cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id].num }}</text>
|
|
||||||
<view class="relative w-[32rpx] h-[32rpx]">
|
|
||||||
<text class="text-[32rpx] text-color iconfont iconjiahao2fill absolute flex items-center justify-center -left-[14rpx] -bottom-[14rpx] -right-[14rpx] -top-[14rpx]"
|
|
||||||
:id="'itemCart' + index"
|
|
||||||
@click.stop="addCartBtn(item,cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id],'itemCart' + index)"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<template v-else-if="(item.goods_type == 'virtual' && config.cart.event !== 'cart') || item.goods_type == 'real'">
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-1'" class="h-[44rpx] relative">
|
|
||||||
<view :id="'itemCart' + index" class="w-[102rpx] box-border text-center text-[#fff] primary-btn-bg h-[46rpx] text-[22rpx] leading-[46rpx] rounded-[100rpx]" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
{{ config.cart.text }}
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-16rpx] top-[-16rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-2'" class="w-[50rpx] h-[50rpx] relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<text :id="'itemCart' + index" class="text-color nc-iconfont nc-icon-tianjiaV6xx text-[44rpx]"></text>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-16rpx] top-[-16rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-3'" class="w-[50rpx] flex justify-center items-end h-[50rpx] relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<text :id="'itemCart' + index"
|
|
||||||
class="text-color nc-iconfont nc-icon-gouwucheV6xx6 !text-[34rpx]"></text>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-10rpx] top-[-2rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-4'" class="w-[50rpx] h-[50rpx] justify-center flex items-end relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<view :id="'itemCart' + index"
|
|
||||||
class=" flex items-center justify-center text-[#fff] bg-color h-[44rpx] w-[44rpx] rounded-[22rpx] text-center">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6xx6 !text-[26rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-10rpx] top-[-10rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<mescroll-empty class="part" v-if="!list.length && !loading && listLoading" :option="{tip : '暂无商品'}"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
<add-cart-popup ref="cartRef" />
|
|
||||||
</mescroll-body>
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view v-if="config.cart.control && config.cart.event === 'cart'"
|
|
||||||
class="bg-[#fff] z-10 flex justify-between items-center fixed left-0 right-0 bottom-[50px] box-solid px-[24rpx] py-[17rpx] mb-ios border-[0] border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="w-[66rpx] h-[66rpx] mr-[27rpx] relative">
|
|
||||||
<view id="animation-end" class="w-[66rpx] h-[66rpx] rounded-[35rpx] bg-[var(--primary-color)] text-center leading-[70rpx]" @click.stop="toCart">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6mm1 text-[#fff] text-[32rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="totalNum"
|
|
||||||
class="border-[1rpx] border-solid border-[#fff]"
|
|
||||||
:class="['absolute left-[40rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ totalNum > 99 ? "99+" : totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-[26rpx] font-500 text-[#333]">总计:</text>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font font-bold flex items-baseline">
|
|
||||||
<text class="text-[26rpx] mr-[6rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx]">{{ parseFloat(totalMoney) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" @click="settlement">去结算</button>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view v-if="config.cart.control && config.cart.event === 'cart'"
|
|
||||||
class="bg-[#fff] z-10 flex justify-between items-center fixed left-0 right-0 bottom-[100rpx] box-solid px-[24rpx] py-[17rpx] mb-ios border-[0] border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="w-[66rpx] h-[66rpx] mr-[27rpx] relative">
|
|
||||||
<view id="animation-end"
|
|
||||||
class="w-[66rpx] h-[66rpx] rounded-[35rpx] bg-[var(--primary-color)] text-center leading-[66rpx]"
|
|
||||||
@click.stop="toCart">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6mm1 text-[#fff] text-[32rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="totalNum"
|
|
||||||
class="border-[1rpx] border-solid border-[#fff]"
|
|
||||||
:class="['absolute left-[40rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ totalNum > 99 ? "99+" : totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-[26rpx] font-500 text-[#333]">总计:</text>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font font-bold inline-block">
|
|
||||||
<text class="text-[26rpx] mr-[6rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx]">{{ parseFloat(totalMoney) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button v-if="isBindMobile && userInfo && !userInfo.mobile" class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">去结算</button>
|
|
||||||
<button v-else class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" @click="settlement">去结算</button>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-show="animationElStatus" :style="animationElStatus"
|
|
||||||
class="fixed z-999 flex items-center justify-center text-[#fff] bg-color h-[44rpx] w-[44rpx] rounded-[22rpx] text-center">
|
|
||||||
<text class=" nc-iconfont nc-icon-gouwucheV6xx6 !text-[30rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!tabsData.length && !loading" :option="{tip : '暂无商品分类'}"></mescroll-empty>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
|
|
||||||
<tabbar />
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted, computed, getCurrentInstance } from 'vue';
|
|
||||||
import { t } from '@/locale';
|
|
||||||
import { img, redirect, getToken } from '@/utils/common';
|
|
||||||
import { getGoodsCategoryTree, getGoodsPages } from '@/addon/shop/api/goods';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import addCartPopup from './add-cart-popup.vue'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
|
|
||||||
// 查询购物车列表
|
|
||||||
cartStore.getList();
|
|
||||||
|
|
||||||
const cartList = computed(() => cartStore.cartList)
|
|
||||||
const totalNum = computed(() => cartStore.totalNum)
|
|
||||||
const totalMoney = computed(() => cartStore.totalMoney)
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
const { mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const prop = defineProps({
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
default: (() => { return {} })
|
|
||||||
},
|
|
||||||
categoryId:{
|
|
||||||
type:[String,Number],
|
|
||||||
default:0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let config = prop.config
|
|
||||||
let categoryId = prop.categoryId;
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const searchName = ref("");
|
|
||||||
const loading = ref<boolean>(true);//页面加载动画
|
|
||||||
const listLoading = ref<boolean>(false);//列表加载动画
|
|
||||||
const cartData = ref<Array<any>>([])
|
|
||||||
const instance = getCurrentInstance(); // 获取组件实例
|
|
||||||
cartData.value = uni.getStorageSync('shopCart') || []
|
|
||||||
interface acceptingDataStructure {
|
|
||||||
data: acceptingDataItemStructure,
|
|
||||||
msg: string,
|
|
||||||
code: number
|
|
||||||
}
|
|
||||||
interface acceptingDataItemStructure {
|
|
||||||
data: object,
|
|
||||||
[propName: string]: number | string | object
|
|
||||||
}
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
const getListFn = (mescroll: mescrollStructure) => {
|
|
||||||
listLoading.value = false
|
|
||||||
getGoodsPages({
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
goods_category: categoryId, // 商品分类id
|
|
||||||
}).then((res: any) => {
|
|
||||||
let newArr = res.data.data
|
|
||||||
//设置列表数据
|
|
||||||
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
// 商品限购
|
|
||||||
goodsMaxBuy();
|
|
||||||
loading.value = false;
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
if (!list.value.length) listLoading.value = true
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
listLoading.value = true
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const goodsMaxBuy = ()=>{
|
|
||||||
list.value.forEach((data,index)=>{
|
|
||||||
data.isMaxBuy = false;
|
|
||||||
|
|
||||||
let maxBuyNum = -1;
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(data.is_limit){
|
|
||||||
if(data.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(data.limit_type == 1){ //单次限购
|
|
||||||
max_buy = data.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = data.max_buy - (data.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(max_buy > data.stock){
|
|
||||||
maxBuyNum = data.stock
|
|
||||||
}else if(max_buy <= data.stock){
|
|
||||||
maxBuyNum = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxBuyNum == 0){
|
|
||||||
data.isMaxBuy = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const toLink = (goods_id: string) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getCategoryData()
|
|
||||||
})
|
|
||||||
|
|
||||||
//设置购物车动画
|
|
||||||
const animationElStatus = ref('')
|
|
||||||
const animationAddRepeatFlag = ref<Boolean>(false)
|
|
||||||
const cartRepeatFlag = ref<Boolean>(false)
|
|
||||||
const animationAddCart = (row: any, id: any) => {
|
|
||||||
if (animationAddRepeatFlag.value || cartRepeatFlag.value) return false
|
|
||||||
animationAddRepeatFlag.value = true
|
|
||||||
cartRepeatFlag.value = true
|
|
||||||
|
|
||||||
let obj: any = {
|
|
||||||
goods_id: row.goodsSku.goods_id,
|
|
||||||
sku_id: row.goodsSku.sku_id,
|
|
||||||
sale_price: goodsPrice(row),
|
|
||||||
stock: row.goodsSku.stock
|
|
||||||
};
|
|
||||||
if (row.id) {
|
|
||||||
obj.num = row.num;
|
|
||||||
obj.id = row.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起购
|
|
||||||
let num = 1;
|
|
||||||
if(row.min_buy > 0 && !row.num){
|
|
||||||
num = row.min_buy;
|
|
||||||
}else{
|
|
||||||
num = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cartStore.increase(obj, num, () => {
|
|
||||||
cartRepeatFlag.value = false
|
|
||||||
});
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.createSelectorQuery().in(instance).select('#animation-end').boundingClientRect((res: any) => {
|
|
||||||
uni.createSelectorQuery().in(instance).select('#' + id).boundingClientRect((position: any) => {
|
|
||||||
animationElStatus.value = `top: ${ position.top }px; left: ${ position.left }px;`
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = `top: ${ res.top + res.height / 2 - position.height / 3 }px; left: ${ res.left + res.width / 2 - position.width / 3 }px; transition: all 0.8s; transform: rotate(-720deg);`
|
|
||||||
}, 20);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = ''
|
|
||||||
animationAddRepeatFlag.value = false
|
|
||||||
}, 1020);
|
|
||||||
|
|
||||||
}).exec()
|
|
||||||
|
|
||||||
}).exec()
|
|
||||||
}, 100)
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
setTimeout(() => {
|
|
||||||
const animationEnd: any = window.document.getElementById('animation-end');
|
|
||||||
const animationEndLeft = animationEnd.getBoundingClientRect().left;
|
|
||||||
const animationEndTop = animationEnd.getBoundingClientRect().top;
|
|
||||||
|
|
||||||
const itemCart: any = window.document.getElementById(id);
|
|
||||||
const itemCartLift = itemCart.getBoundingClientRect().left;
|
|
||||||
const itemCartTop = itemCart.getBoundingClientRect().top;
|
|
||||||
animationElStatus.value = `top: ${ itemCartTop }px; left: ${ itemCartLift }px;`
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = `top: ${ animationEndTop + animationEnd.offsetHeight / 2 - itemCart.offsetHeight / 3 }px; left: ${ animationEndLeft + animationEnd.offsetWidth / 2 - itemCart.offsetHeight / 3 }px; transition: all 0.8s; transform: rotate(-720deg);`
|
|
||||||
}, 20);
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = ''
|
|
||||||
animationAddRepeatFlag.value = false
|
|
||||||
}, 1020);
|
|
||||||
|
|
||||||
}, 100);
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 获取分类数据
|
|
||||||
* */
|
|
||||||
const tabsData:any = ref<Array<Object>>([])
|
|
||||||
const getCategoryData = () => {
|
|
||||||
loading.value = true;
|
|
||||||
getGoodsCategoryTree().then((res: any) => {
|
|
||||||
tabsData.value = res.data;
|
|
||||||
if (categoryId) {
|
|
||||||
for (let i = 0; i < tabsData.value.length; i++) {
|
|
||||||
if (tabsData.value[i].category_id == categoryId) {
|
|
||||||
tabActive.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(tabsData.value[i].child_list){
|
|
||||||
for(let k=0;k<tabsData.value[i].child_list.length;k++){
|
|
||||||
if(tabsData.value[i].child_list[k].category_id == categoryId){
|
|
||||||
tabActive.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
categoryId = res.data[0].category_id;
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 一级菜单样式控制
|
|
||||||
const tabActive = ref<number>(0)
|
|
||||||
|
|
||||||
// 一级菜单点击事件
|
|
||||||
const firstLevelClick = (index: number, data: any) => {
|
|
||||||
tabActive.value = index;
|
|
||||||
categoryId = data.category_id;
|
|
||||||
list.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索名字
|
|
||||||
const searchNameFn = () => {
|
|
||||||
// getMescroll().resetUpScroll();
|
|
||||||
if(searchName.value) redirect({ url: '/addon/shop/pages/goods/list', param: { goods_name: encodeURIComponent(searchName.value) } })
|
|
||||||
}
|
|
||||||
|
|
||||||
//点击商品购物车按钮
|
|
||||||
const cartRef = ref()
|
|
||||||
const itemCart = (row: any, id: any) => {
|
|
||||||
// 虚拟商品,并且需要核销,禁止加入购物车
|
|
||||||
if(row.goods_type == 'virtual' && row.virtual_receive_type == 'verify'){
|
|
||||||
return toLink(row.goodsSku.goods_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.cart.event !== 'cart') {
|
|
||||||
return toLink(row.goodsSku.goods_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({ url: '/addon/shop/pages/goods/category' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.goodsSku.sku_spec_format) {
|
|
||||||
cartRef.value.open(row.goodsSku.sku_id)
|
|
||||||
} else {
|
|
||||||
//单规格添加购物车
|
|
||||||
if (!row.goodsSku.stock || parseInt(row.goodsSku.num||0) > parseInt(row.goodsSku.stock)) {
|
|
||||||
uni.showToast({ title: '商品库存不足', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(row.min_buy && row.min_buy > parseInt(row.stock)){
|
|
||||||
uni.showToast({ title: '商品库存小于起购数量', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
animationAddCart(row, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//点击购物车加号 添加数量
|
|
||||||
const addCartBtn = (item: any, row: any, id: string) => {
|
|
||||||
if (parseInt(row.num) >= parseInt(row.stock)) {
|
|
||||||
uni.showToast({ title: '商品库存不足', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起购
|
|
||||||
let num = row.num;
|
|
||||||
if(item.min_buy > 0 && item.min_buy > num){
|
|
||||||
num = item.min_buy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************** 限购-start *****************/
|
|
||||||
let maxBuyNum = -1;
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(item.is_limit && item.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(item.limit_type == 1){ //单次限购
|
|
||||||
max_buy = item.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = item.max_buy - (item.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(max_buy > item.goodsSku.stock){
|
|
||||||
maxBuyNum = item.goodsSku.stock
|
|
||||||
}else if(max_buy <= item.goodsSku.stock){
|
|
||||||
maxBuyNum = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(item.is_limit && num >= item.max_buy){
|
|
||||||
let tips = `该商品单次限购${item.max_buy}件`;
|
|
||||||
if(item.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${item.max_buy}件`;
|
|
||||||
}
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/************** 限购-end *****************/
|
|
||||||
|
|
||||||
let obj = cloneDeep(item)
|
|
||||||
obj.num = num;
|
|
||||||
obj.id = row.id;
|
|
||||||
animationAddCart(obj, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
//点击购物车减号
|
|
||||||
const reduceCart = (data: any, row: any) => {
|
|
||||||
if(cartRepeatFlag.value) return false
|
|
||||||
cartRepeatFlag.value = true
|
|
||||||
|
|
||||||
let reduceNum = 1;
|
|
||||||
if(data.min_buy > 0 && data.min_buy == row.num){
|
|
||||||
reduceNum = data.min_buy;
|
|
||||||
}
|
|
||||||
|
|
||||||
cartStore.reduce({
|
|
||||||
id: row.id,
|
|
||||||
goods_id: row.goods_id,
|
|
||||||
sku_id: row.sku_id,
|
|
||||||
stock: row.stock,
|
|
||||||
sale_price: row.sale_price,
|
|
||||||
num: row.num
|
|
||||||
}, reduceNum, () => {
|
|
||||||
cartRepeatFlag.value = false
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//进入购物车
|
|
||||||
const toCart = () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/cart' })
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const isBindMobile = ref(uni.getStorageSync('isbindmobile'))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 结算
|
|
||||||
*/
|
|
||||||
const settlement = () => {
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
// 绑定手机号
|
|
||||||
if(uni.getStorageSync('isbindmobile')){
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
if (!totalNum.value) {
|
|
||||||
uni.showToast({ title: '还没有选择商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const cart_ids:any = []
|
|
||||||
Object.values(cartList.value).forEach(item => {
|
|
||||||
Object.keys(item).forEach(v => {
|
|
||||||
if (v != 'totalNum' && v != 'totalMoney') cart_ids.push(item[v].id)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
if(cart_ids.length == 0){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'orderCreateData',
|
|
||||||
data: { cart_ids },
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/payment' })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 价格类型
|
|
||||||
const priceType = (data:any) =>{
|
|
||||||
let type = "";
|
|
||||||
if(data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
type = 'member_price' // 会员价
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = (data:any) =>{
|
|
||||||
let price = "0.00";
|
|
||||||
if (data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
price = data.goodsSku.member_price ? data.goodsSku.member_price : data.goodsSku.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = data.goodsSku.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.border-color {
|
|
||||||
border-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
height: 6rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
width: 90%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-select {
|
|
||||||
position: relative;
|
|
||||||
margin-right: 28rpx;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background-color: #999;
|
|
||||||
width: 2rpx;
|
|
||||||
height: 70%;
|
|
||||||
top: 50%;
|
|
||||||
right: -14rpx;
|
|
||||||
transform: translatey(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.transform-rotate {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// search input
|
|
||||||
.search-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt {
|
|
||||||
height: 58rpx;
|
|
||||||
background-color: #F6F8F8;
|
|
||||||
border-radius: 33rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt .input-placeholder {
|
|
||||||
color: #A5A6A6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box {
|
|
||||||
width: 168rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box .tab-item {
|
|
||||||
min-height: 56rpx;
|
|
||||||
padding: 20rpx 0;
|
|
||||||
text-align: center;
|
|
||||||
background-color:#fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box .tab-item-active {
|
|
||||||
position: relative;
|
|
||||||
color: var(--primary-color);
|
|
||||||
background-color:var(--temp-bg);
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-height{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.cart{
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.detail{
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.cart{
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.detail{
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
// 空页面
|
|
||||||
.mescroll-empty.empty-page.part{
|
|
||||||
width: 542rpx;
|
|
||||||
height: 542rpx;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
padding-top: 50rpx;
|
|
||||||
.img{
|
|
||||||
width: 160rpx !important;
|
|
||||||
height: 120rpx !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,306 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class=" bg-[var(--page-bg-color)] overflow-hidden min-h-screen">
|
|
||||||
<view class="mescroll-box" v-if="tabsData.length">
|
|
||||||
<view v-if="config.search.control" class="search-box box-border z-10 fixed top-0 left-0 right-0 h-[100rpx] bg-[#fff]">
|
|
||||||
<view class="flex-1 search-input">
|
|
||||||
<text @click.stop="searchNameFn" class="nc-iconfont nc-icon-sousuo-duanV6xx1 btn"></text>
|
|
||||||
<input class="input" type="text" v-model="searchName" :placeholder="config.search.title" placeholderClass="text-[var(--text-color-light9)]" @confirm="searchNameFn">
|
|
||||||
<text v-if="searchName" class="nc-iconfont nc-icon-cuohaoV6xx1 clear" @click="searchName=''"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="tabs-box z-2 fixed left-0 bg-[#fff] bottom-[50px] top-0" :class="{ '!top-[100rpx]': config.search.control }">
|
|
||||||
<scroll-view :scroll-y="true" class="scroll-height">
|
|
||||||
<view class="bg-[var(--temp-bg)]">
|
|
||||||
<view class="tab-item" :class="{ 'tab-item-active': index == tabActive,'rounded-br-[12rpx]':tabActive-1===index,'rounded-tr-[12rpx]':tabActive+1===index }" v-for="(item, index) in tabsData" :key="index" @click="firstLevelClick(index, item)">
|
|
||||||
<view class="text-box text-left leading-[1.3] break-words px-[16rpx]">
|
|
||||||
{{ item.category_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<scroll-view class="h-[100vh]" :scroll-y="true">
|
|
||||||
<view class="pl-[188rpx] scroll-ios pt-[20rpx] pr-[20rpx]" :class="{ '!pt-[120rpx]': config.search.control }">
|
|
||||||
<view class="bg-[#fff] grid grid-cols-3 gap-x-[50rpx] gap-y-[32rpx] py-[32rpx] px-[24rpx] rounded-[var(--rounded-big)]" v-if="tabsData[tabActive]?.child_list && !loading">
|
|
||||||
<template v-for="(item, index) in tabsData[tabActive]?.child_list" :key="item.category_id">
|
|
||||||
<view @click="toLink(item.category_id)" class=" flex items-center justify-center flex-col">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="120rpx" height="120rpx" :src="img(item.image ? item.image : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="rounded-[var(--goods-rounded-big)] overflow-hidden w-[120rpx] h-[120rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="text-[24rpx] text-center mt-[16rpx] leading-[34rpx]">{{ item.category_name }}</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty class="part" v-if="!tabsData[tabActive]?.child_list && !loading" :option="{tip : '暂无商品分类'}"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<tabbar />
|
|
||||||
<mescroll-empty v-if="!tabsData.length && !loading" :option="{tip : '暂无商品分类'}"></mescroll-empty>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted } from 'vue';
|
|
||||||
import { img, redirect } from '@/utils/common';
|
|
||||||
import { getGoodsCategoryTree } from '@/addon/shop/api/goods';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import { t } from '@/locale';
|
|
||||||
|
|
||||||
const prop = defineProps({
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
default: (() => {
|
|
||||||
return {}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
categoryId: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let config = prop.config
|
|
||||||
let categoryId = prop.categoryId;
|
|
||||||
const searchName = ref("");
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getCategoryData()
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 获取分类数据
|
|
||||||
* */
|
|
||||||
const tabsData: any = ref<Array<Object>>([])
|
|
||||||
const getCategoryData = () => {
|
|
||||||
loading.value = true;
|
|
||||||
getGoodsCategoryTree().then((res: any) => {
|
|
||||||
tabsData.value = res.data;
|
|
||||||
if (categoryId) {
|
|
||||||
for (let i = 0; i < tabsData.value.length; i++) {
|
|
||||||
if (tabsData.value[i].category_id == categoryId) {
|
|
||||||
tabActive.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(tabsData.value[i].child_list){
|
|
||||||
for(let k=0;k<tabsData.value[i].child_list.length;k++){
|
|
||||||
if(tabsData.value[i].child_list[k].category_id == categoryId){
|
|
||||||
tabActive.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 一级菜单样式控制
|
|
||||||
const tabActive = ref<number>(0)
|
|
||||||
|
|
||||||
// 一级菜单点击事件
|
|
||||||
const firstLevelClick = (index: number, data: Object) => {
|
|
||||||
tabActive.value = index;
|
|
||||||
}
|
|
||||||
const toLink = (curr_goods_category: string) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/list', param: { curr_goods_category } })
|
|
||||||
}
|
|
||||||
// 搜索名字
|
|
||||||
const searchNameFn = () => {
|
|
||||||
// getMescroll().resetUpScroll();
|
|
||||||
if(searchName.value) redirect({ url: '/addon/shop/pages/goods/list', param: { goods_name: encodeURIComponent(searchName.value) } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.border-color {
|
|
||||||
border-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
height: 6rpx;
|
|
||||||
background-color: $u-primary;
|
|
||||||
width: 90%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-select {
|
|
||||||
position: relative;
|
|
||||||
margin-right: 28rpx;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background-color: #999;
|
|
||||||
width: 2rpx;
|
|
||||||
height: 70%;
|
|
||||||
top: 50%;
|
|
||||||
right: -14rpx;
|
|
||||||
transform: translatey(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.transform-rotate {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt {
|
|
||||||
height: 58rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 33rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt .input-placeholder {
|
|
||||||
color: #A5A6A6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box {
|
|
||||||
width: 168rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box .tab-item {
|
|
||||||
min-height: 48rpx;
|
|
||||||
padding: 18rpx 0;
|
|
||||||
text-align: center;
|
|
||||||
background-color:#fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box .tab-item-active {
|
|
||||||
position: relative;
|
|
||||||
color: var(--primary-color);
|
|
||||||
background-color: var(--temp-bg);
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$white-bj: #fff;
|
|
||||||
|
|
||||||
.mescroll-box {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panic-buying {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
color: $white-bj;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.mescroll-upwarp) {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-left: 182rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-bar-placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar__placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.scroll-ios{
|
|
||||||
padding-bottom: calc(50px + 20rpx + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(50px + 20rpx + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.scroll-ios{
|
|
||||||
padding-bottom: calc(120rpx + constant(safe-area-inset-bottom)) !important;
|
|
||||||
padding-bottom: calc(120rpx + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
.scroll-height{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
.mescroll-empty.empty-page.part{
|
|
||||||
width: 542rpx;
|
|
||||||
height: 542rpx;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
padding-top: 50rpx;
|
|
||||||
.img{
|
|
||||||
width: 160rpx !important;
|
|
||||||
height: 120rpx !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,896 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="min-h-screen bg-[var(--page-bg-color)] overflow-hidden">
|
|
||||||
<view class="mescroll-box bg-[#f6f6f6]" :class="{ 'cart': config.cart.control && config.cart.event === 'cart', 'detail': !(config.cart.control && config.cart.event === 'cart') }" v-if="tabsData.length">
|
|
||||||
<mescroll-body ref="mescrollRef" :down="{ use: false }" @init="mescrollInit" @up="getListFn">
|
|
||||||
<view v-if="config.search.control" class="box-border search-box z-10 bg-[#fff] fixed top-0 left-0 right-0 h-[96rpx]">
|
|
||||||
<view class="flex-1 search-input">
|
|
||||||
<text @click.stop="searchNameFn" class="nc-iconfont nc-icon-sousuo-duanV6xx1 btn"></text>
|
|
||||||
<input class="input" type="text" v-model="searchName" :placeholder="config.search.title" placeholderClass="text-[var(--text-color-light9)]" @confirm="searchNameFn">
|
|
||||||
<text v-if="searchName" class="nc-iconfont nc-icon-cuohaoV6xx1 clear" @click="searchName=''"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view class="tabs-box z-2 fixed left-0 bg-[#fff] bottom-[50px] top-0" :class="{ '!top-[96rpx]': config.search.control, 'pb-[98rpx]': config.cart.control && config.cart.event === 'cart' }">
|
|
||||||
<scroll-view :scroll-y="true" class="scroll-height">
|
|
||||||
<view class="bg-[var(--temp-bg)]">
|
|
||||||
<view class="tab-item"
|
|
||||||
:class="{ 'tab-item-active ': index == tabActive,'rounded-br-[12rpx]':tabActive-1===index && (!tabsData[tabActive].child_list || !tabsData[tabActive].child_list.length),'rounded-tr-[12rpx]':tabActive+1===index&&(!tabsData[tabActive].child_list || !tabsData[tabActive].child_list.length) }" v-for="(item, index) in tabsData" :key="index" @click="firstLevelClick(index, item)">
|
|
||||||
<view class="text-box leading-[1.3] break-words px-[24rpx]">{{ item.category_name }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifndef H5 -->
|
|
||||||
<view class="tabs-box z-2 fixed left-0 bg-[#fff] pb-ios bottom-[100rpx] top-0" :class="{ 'top-[96rpx]': config.search.control, '!bottom-[198rpx]': config.cart.control && config.cart.event === 'cart' }">
|
|
||||||
<scroll-view :scroll-y="true" class="scroll-height">
|
|
||||||
<view class="bg-[var(--temp-bg)]">
|
|
||||||
<view class="tab-item" :class="{ 'tab-item-active': index == tabActive,'rounded-br-[12rpx]':tabActive-1===index&&(!tabsData[tabActive].child_list || !tabsData[tabActive].child_list.length),'rounded-tr-[12rpx]':tabActive+1===index&&(!tabsData[tabActive].child_list || !tabsData[tabActive].child_list.length) }" v-for="(item, index) in tabsData" :key="index" @click="firstLevelClick(index, item)">
|
|
||||||
<view class="text-box px-[16rpx] leading-[1.3] break-words">
|
|
||||||
{{ item.category_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="flex items-center h-[98rpx] pl-[24rpx] pr-[48rpx] py-[20rpx] z-10 bg-white fixed left-[168rpx] right-0 box-border top-0"
|
|
||||||
:class="{ '!top-[94rpx]': config.search.control }"
|
|
||||||
v-if="tabsData[tabActive]?.child_list && tabsData[tabActive]?.child_list.length">
|
|
||||||
<template v-if="!labelPopup">
|
|
||||||
<scroll-view :scroll-x="true" scroll-with-animation
|
|
||||||
:scroll-into-view="'id' + (subActive ? subActive - 1 : 0)"
|
|
||||||
class="flex-1 h-[54rpx] scroll-Y box-border pr-[24rpx] bg-white">
|
|
||||||
<view class="flex items-center h-[54rpx] box-border">
|
|
||||||
<text
|
|
||||||
class="w-[150rpx] flex-shrink-0 px-[14rpx] h-[54rpx] truncate text-center !leading-[50rpx] !text-[24rpx] border-[2rpx] border-solid !rounded-[100rpx] box-border text-[#333] box-border"
|
|
||||||
:class="{ 'bg-[var(--primary-color-light)] font-500 text-[var(--primary-color)] border-[var(--primary-color)]': index === subActive, 'border-[var(--temp-bg)] bg-[var(--temp-bg)]': index != subActive, ' ml-[24rpx]': index != 0 }"
|
|
||||||
v-for="(item, index) in tabsData[tabActive]?.child_list"
|
|
||||||
:key="tabsData[tabActive].category_id" :id="'id' + index"
|
|
||||||
@click="subMenuClick(index, item)">{{ item.category_name }}</text>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="absolute right-[24rpx] nc-iconfont nc-icon-xiaV6xx text-[30rpx] w-[30rpx] h-[30rpx] text-center transform " @click="labelPopup = true"></view>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<view class="flex-1 h-[48rpx] text-[28rpx] text-[var(--text-color-light9)] pr-[24rpx] leading-[48rpx]">全部分类</view>
|
|
||||||
<text class="absolute right-[24rpx] nc-iconfont nc-icon-shangV6xx-1 text-[#333] text-[30rpx]" @click="labelPopup = false"></text>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="labelPopup" :class="{ 'active': config.search.control }">
|
|
||||||
<u-popup :show="labelPopup" mode="top" @close="labelPopup = false">
|
|
||||||
<view class="flex flex-wrap pt-[20rpx] pb-[24rpx]" @touchmove.prevent.stop>
|
|
||||||
<text
|
|
||||||
class="px-[14rpx] flex-shrink-0 w-[160rpx] box-border ml-[20rpx] mb-[26rpx] h-[60rpx] text-center leading-[56rpx] text-[24rpx] border-[2rpx] border-solid !rounded-[100rpx] text-[#333] truncate"
|
|
||||||
:class="{ 'bg-[var(--primary-color-light)] font-500 text-[var(--primary-color)] border-[var(--primary-color)]': index === subActive, 'border-[var(--temp-bg)] bg-[var(--temp-bg)]': index != subActive }"
|
|
||||||
v-for="(item, index) in tabsData[tabActive]?.child_list"
|
|
||||||
:key="tabsData[tabActive].category_id" @click="subMenuClick(index, item)">{{ item.category_name }}</text>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-center flex-wrap pl-[168rpx] pt-[20rpx] pb-[20rpx]"
|
|
||||||
:class="{ '!pt-[214rpx]': config.search.control && tabsData[tabActive]?.child_list && tabsData[tabActive]?.child_list.length, 'pt-[120rpx]': config.search.control && (!tabsData[tabActive].child_list || !tabsData[tabActive].child_list.length), 'pt-[118rpx]': tabsData[tabActive]?.child_list && tabsData[tabActive]?.child_list.length && !config.search.control }">
|
|
||||||
<template v-for="(item, index) in list" :key="item.goods_id">
|
|
||||||
<view
|
|
||||||
class="w-[536rpx] box-border bg-white w-full flex mx-[20rpx] py-[24rpx] px-[20rpx] rounded-[var(--rounded-small)]"
|
|
||||||
:class="{ 'mt-[20rpx]': index }" @click.stop="toLink(item.goods_id)">
|
|
||||||
<view class="w-[168rpx] h-[168rpx] flex items-center justify-center mr-[20rpx] rounded-[var(--goods-rounded-small)] overflow-hidden">
|
|
||||||
<u--image width="168rpx" height="168rpx" :radius="'var(--goods-rounded-small)'" :src="img( item.goods_cover_thumb_mid || '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[168rpx] h-[168rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-wrap flex-col">
|
|
||||||
<view class="max-h-[80rpx] text-[26rpx] leading-[40rpx] multi-hidden">
|
|
||||||
{{ item.goods_name }}</view>
|
|
||||||
<view class="flex items-end justify-between flex-1">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font -mb-[8rpx]">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsPrice(item)).toFixed(2).split('.')[1] }}</text>
|
|
||||||
<image class="h-[24rpx] max-w-[46rpx] ml-[6rpx]" v-if="priceType(item) == 'member_price'" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<block v-if="!item.isMaxBuy">
|
|
||||||
<view
|
|
||||||
v-if="(item.goods_type == 'real' || (item.goods_type == 'virtual' && item.virtual_receive_type != 'verify')) &&
|
|
||||||
item.goodsSku.sku_spec_format === '' && cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id] && config.cart.control && config.cart.event === 'cart'"
|
|
||||||
class="flex items-center">
|
|
||||||
<view class="relative w-[32rpx] h-[32rpx]">
|
|
||||||
<text class="text-[32rpx] text-color nc-iconfont nc-icon-jianshaoV6xx absolute flex items-center justify-center -left-[12rpx] -bottom-[14rpx] -right-[14rpx] -top-[14rpx]" @click.stop="reduceCart(item,cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id])"></text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[#333] text-[24rpx] mx-[16rpx]">{{ cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id].num }}</text>
|
|
||||||
<view class="relative w-[32rpx] h-[32rpx]">
|
|
||||||
<text class="text-[32rpx] text-color iconfont iconjiahao2fill absolute flex items-center justify-center -left-[14rpx] -bottom-[14rpx] -right-[14rpx] -top-[14rpx]" :id="'itemCart' + index" @click.stop="addCartBtn(item,cartList['goods_' + item.goods_id]['sku_' + item.goodsSku.sku_id], 'itemCart' + index)"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<template v-else-if="(item.goods_type == 'virtual' && config.cart.event !== 'cart') || item.goods_type == 'real'">
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-1'" class="h-[44rpx] relative pl-[20rpx]">
|
|
||||||
<view :id="'itemCart' + index"
|
|
||||||
class="w-[102rpx] box-border text-center text-[#fff] primary-btn-bg h-[46rpx] text-[22rpx] leading-[46rpx] rounded-[100rpx]"
|
|
||||||
@click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
{{ config.cart.text }}
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-16rpx] top-[-16rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-2'" class="w-[50rpx] h-[50rpx] relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<text :id="'itemCart' + index"
|
|
||||||
class="text-color nc-iconfont nc-icon-tianjiaV6xx text-[44rpx]"></text>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-16rpx] top-[-16rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-3'" class="w-[50rpx] h-[50rpx] flex justify-center items-end relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<text :id="'itemCart' + index"
|
|
||||||
class="text-color nc-iconfont nc-icon-gouwucheV6xx6 !text-[34rpx]"></text>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-10rpx] top-[-2rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="config.cart.control && config.cart.style === 'style-4'" class="w-[50rpx] h-[50rpx] flex items-end relative" @click.stop="itemCart(item, 'itemCart' + index)">
|
|
||||||
<view :id="'itemCart' + index"
|
|
||||||
class=" flex items-center justify-center text-[#fff] bg-color h-[44rpx] w-[44rpx] rounded-[22rpx] text-center">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6xx6 !text-[26rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id].totalNum"
|
|
||||||
:class="['absolute right-[-10rpx] top-[-10rpx] rounded-[30rpx] h-[30rpx] min-w-[30rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border border-[2rpx] border-solid border-[#fff]', cartList['goods_' + item.goods_id].totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ cartList['goods_' + item.goods_id].totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<mescroll-empty class="part" v-if="!list.length && !loading && listLoading" :option="{tip : '暂无商品'}"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
<add-cart-popup ref="cartRef" />
|
|
||||||
</mescroll-body>
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view v-if="config.cart.control && config.cart.event === 'cart'" class="bg-[#fff] z-10 flex justify-between items-center fixed left-0 right-0 bottom-[50px] box-solid px-[24rpx] py-[17rpx] mb-ios border-[0] border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="w-[66rpx] h-[66rpx] mr-[27rpx] relative">
|
|
||||||
<view id="animation-end" class="w-[66rpx] h-[66rpx] rounded-[35rpx] bg-[var(--primary-color)] text-center leading-[70rpx]" @click.stop="toCart">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6mm1 text-[#fff] text-[32rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="totalNum"
|
|
||||||
class="border-[1rpx] border-solid border-[#fff]"
|
|
||||||
:class="['absolute left-[40rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ totalNum > 99 ? "99+" : totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-[26rpx] text-[#333]">总计:</text>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font font-bold flex items-baseline">
|
|
||||||
<text class="text-[26rpx] mr-[6rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx]">{{ parseFloat(totalMoney) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" @click="settlement">去结算</button>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view v-if="config.cart.control && config.cart.event === 'cart'"
|
|
||||||
class="bg-[#fff] z-10 flex justify-between items-center fixed left-0 right-0 bottom-[100rpx] box-solid px-[24rpx] py-[17rpx] mb-ios border-[0] border-t-[2rpx] border-solid border-[#f6f6f6]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="w-[66rpx] h-[66rpx] mr-[27rpx] relative">
|
|
||||||
<view id="animation-end" class="w-[66rpx] h-[66rpx] rounded-[35rpx] bg-[var(--primary-color)] text-center leading-[66rpx]" @click.stop="toCart">
|
|
||||||
<text class="nc-iconfont nc-icon-gouwucheV6mm1 text-[#fff] text-[32rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="totalNum"
|
|
||||||
class="border-[1rpx] border-solid border-[#fff]"
|
|
||||||
:class="['absolute left-[40rpx] top-[-10rpx] rounded-[28rpx] h-[28rpx] min-w-[28rpx] text-center leading-[26rpx] bg-[#FF4646] text-[#fff] text-[20rpx] font-500 box-border', totalNum > 9 ? 'px-[10rpx]' : '']">
|
|
||||||
{{ totalNum > 99 ? "99+" : totalNum }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-[26rpx] text-[#333]">总计:</text>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font font-bold inline-block">
|
|
||||||
<text class="text-[26rpx] mr-[6rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx]">{{ parseFloat(totalMoney) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button v-if="isBindMobile && userInfo && !userInfo.mobile" class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">去结算</button>
|
|
||||||
<button v-else class="w-[180rpx] h-[70rpx] text-[26rpx] leading-[70rpx] font-500 m-0 rounded-full remove-border" :class="{'primary-btn-bg !text-[#fff]': parseFloat(totalMoney) > 0, 'bg-[#F7F7F7] !text-[var(--text-color-light9)]': parseFloat(totalMoney) <= 0}" @click="settlement">去结算</button>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-show="animationElStatus" :style="animationElStatus"
|
|
||||||
class="fixed z-999 flex items-center justify-center text-[#fff] bg-color h-[44rpx] w-[44rpx] rounded-[22rpx] text-center">
|
|
||||||
<text class=" nc-iconfont nc-icon-gouwucheV6xx6 !text-[30rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-center items-center w-[100%]" v-if="!tabsData.length && !loading">
|
|
||||||
<mescroll-empty :option="{tip : '暂无商品分类'}"></mescroll-empty>
|
|
||||||
</view>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
<tabbar />
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted, computed, getCurrentInstance } from 'vue';
|
|
||||||
import { t } from '@/locale';
|
|
||||||
import { img, redirect, getToken } from '@/utils/common';
|
|
||||||
import { getGoodsCategoryTree, getGoodsPages } from '@/addon/shop/api/goods';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import addCartPopup from './add-cart-popup.vue'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import useCartStore from '@/addon/shop/stores/cart'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
const instance = getCurrentInstance(); // 获取组件实例
|
|
||||||
const cartStore = useCartStore();
|
|
||||||
// 查询购物车列表
|
|
||||||
cartStore.getList();
|
|
||||||
|
|
||||||
const cartList = computed(() => cartStore.cartList)
|
|
||||||
const totalNum = computed(() => cartStore.totalNum)
|
|
||||||
const totalMoney = computed(() => cartStore.totalMoney)
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
const { mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const prop = defineProps({
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
default: (() => { return {} })
|
|
||||||
},
|
|
||||||
categoryId:{
|
|
||||||
type:[String,Number],
|
|
||||||
default:0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let config = prop.config
|
|
||||||
let categoryId = prop.categoryId;
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const searchName = ref("");
|
|
||||||
const loading = ref<boolean>(true);//页面加载动画
|
|
||||||
const listLoading = ref<boolean>(false);//列表加载动画
|
|
||||||
const labelPopup = ref<boolean>(false)
|
|
||||||
const cartData = ref<Array<any>>([])
|
|
||||||
cartData.value = uni.getStorageSync('shopCart') || []
|
|
||||||
interface acceptingDataStructure {
|
|
||||||
data: acceptingDataItemStructure,
|
|
||||||
msg: string,
|
|
||||||
code: number
|
|
||||||
}
|
|
||||||
interface acceptingDataItemStructure {
|
|
||||||
data: object,
|
|
||||||
[propName: string]: number | string | object
|
|
||||||
}
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
const getListFn = (mescroll: mescrollStructure) => {
|
|
||||||
listLoading.value = false
|
|
||||||
getGoodsPages({
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
goods_category: categoryId, // 商品分类id
|
|
||||||
}).then((res: any) => {
|
|
||||||
let newArr = res.data.data
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
// 商品限购
|
|
||||||
goodsMaxBuy();
|
|
||||||
loading.value = false;
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
if (!list.value.length) listLoading.value = true
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
listLoading.value = true
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsMaxBuy = ()=>{
|
|
||||||
list.value.forEach((data,index)=>{
|
|
||||||
data.isMaxBuy = false;
|
|
||||||
|
|
||||||
let maxBuyNum = -1;
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(data.is_limit){
|
|
||||||
if(data.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(data.limit_type == 1){ //单次限购
|
|
||||||
max_buy = data.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = data.max_buy - (data.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(max_buy > data.stock){
|
|
||||||
maxBuyNum = data.stock
|
|
||||||
}else if(max_buy <= data.stock){
|
|
||||||
maxBuyNum = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(maxBuyNum == 0){
|
|
||||||
data.isMaxBuy = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (goods_id: string) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getCategoryData()
|
|
||||||
})
|
|
||||||
|
|
||||||
//设置购物车动画
|
|
||||||
const animationElStatus = ref('')
|
|
||||||
const animationAddRepeatFlag = ref<Boolean>(false)
|
|
||||||
const cartRepeatFlag = ref<Boolean>(false)
|
|
||||||
const animationAddCart = (row: any, id: any) => {
|
|
||||||
if (animationAddRepeatFlag.value || cartRepeatFlag.value) return false
|
|
||||||
animationAddRepeatFlag.value = true
|
|
||||||
cartRepeatFlag.value = true
|
|
||||||
|
|
||||||
let obj: any = {
|
|
||||||
goods_id: row.goodsSku.goods_id,
|
|
||||||
sku_id: row.goodsSku.sku_id,
|
|
||||||
sale_price: goodsPrice(row),
|
|
||||||
stock: row.goodsSku.stock
|
|
||||||
};
|
|
||||||
if (row.id) {
|
|
||||||
obj.num = row.num;
|
|
||||||
obj.id = row.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起购
|
|
||||||
let num = 1;
|
|
||||||
if(row.min_buy > 0 && !row.num){
|
|
||||||
num = row.min_buy;
|
|
||||||
}else{
|
|
||||||
num = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cartStore.increase(obj, num, () => {
|
|
||||||
cartRepeatFlag.value = false
|
|
||||||
});
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.createSelectorQuery().in(instance).select('#animation-end').boundingClientRect((res: any) => {
|
|
||||||
uni.createSelectorQuery().in(instance).select('#' + id).boundingClientRect((position: any) => {
|
|
||||||
animationElStatus.value = `top: ${ position.top }px; left: ${ position.left }px;`
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = `top: ${ res.top + res.height / 2 - position.height / 3 }px; left: ${ res.left + res.width / 2 - position.width / 3 }px; transition: all 0.8s; transform: rotate(-720deg);`
|
|
||||||
}, 20);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = ''
|
|
||||||
animationAddRepeatFlag.value = false
|
|
||||||
}, 1020);
|
|
||||||
|
|
||||||
}).exec()
|
|
||||||
|
|
||||||
}).exec()
|
|
||||||
}, 100)
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
setTimeout(() => {
|
|
||||||
const animationEnd: any = window.document.getElementById('animation-end');
|
|
||||||
const animationEndLeft = animationEnd.getBoundingClientRect().left;
|
|
||||||
const animationEndTop = animationEnd.getBoundingClientRect().top;
|
|
||||||
|
|
||||||
const itemCart: any = window.document.getElementById(id);
|
|
||||||
const itemCartLift = itemCart.getBoundingClientRect().left;
|
|
||||||
const itemCartTop = itemCart.getBoundingClientRect().top;
|
|
||||||
animationElStatus.value = `top: ${ itemCartTop }px; left: ${ itemCartLift }px;`
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = `top: ${ animationEndTop + animationEnd.offsetHeight / 2 - itemCart.offsetHeight / 3 }px; left: ${ animationEndLeft + animationEnd.offsetWidth / 2 - itemCart.offsetHeight / 3 }px; transition: all 0.8s; transform: rotate(-720deg);`
|
|
||||||
}, 20);
|
|
||||||
setTimeout(() => {
|
|
||||||
animationElStatus.value = ''
|
|
||||||
animationAddRepeatFlag.value = false
|
|
||||||
}, 1020);
|
|
||||||
|
|
||||||
}, 100);
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取购物车数据
|
|
||||||
* @description 获取分类数据
|
|
||||||
* */
|
|
||||||
const initAll = ref({
|
|
||||||
allActive : -1,
|
|
||||||
data: { category_name: "全部", category_id: '' }
|
|
||||||
})
|
|
||||||
const tabsData:any = ref<Array<Object>>([])
|
|
||||||
const getCategoryData = () => {
|
|
||||||
loading.value = true;
|
|
||||||
getGoodsCategoryTree().then((res: any) => {
|
|
||||||
tabsData.value = res.data;
|
|
||||||
for (let i = 0; i < tabsData.value.length; i++) {
|
|
||||||
if(tabsData.value[i].child_list){
|
|
||||||
let obj = {
|
|
||||||
category_name: "全部",
|
|
||||||
category_id: tabsData.value[i].category_id
|
|
||||||
};
|
|
||||||
tabsData.value[i].child_list.unshift(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (categoryId) {
|
|
||||||
for (let i = 0; i < tabsData.value.length; i++) {
|
|
||||||
if (tabsData.value[i].category_id == categoryId) {
|
|
||||||
tabActive.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(tabsData.value[i].child_list){
|
|
||||||
for(let k=0;k<tabsData.value[i].child_list.length;k++){
|
|
||||||
if(tabsData.value[i].child_list[k].category_id == categoryId){
|
|
||||||
tabActive.value = i;
|
|
||||||
subActive.value = k;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
categoryId = res.data[0].category_id;
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 一级菜单样式控制
|
|
||||||
const tabActive = ref<number>(0)
|
|
||||||
// 二级菜单样式控制
|
|
||||||
const subActive = ref<number>(0)
|
|
||||||
|
|
||||||
// 一级菜单点击事件
|
|
||||||
const firstLevelClick = (index: number, data: any) => {
|
|
||||||
tabActive.value = index;
|
|
||||||
if (data.child_list && data.child_list.length) {
|
|
||||||
subMenuClick(0, data.child_list[0]);
|
|
||||||
} else {
|
|
||||||
categoryId = data.category_id;
|
|
||||||
list.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 二级菜单点击事件
|
|
||||||
* @param {number} index
|
|
||||||
* @param {Object} data
|
|
||||||
* */
|
|
||||||
const subMenuClick = (index: number, data: any) => {
|
|
||||||
subActive.value = index;
|
|
||||||
categoryId = data.category_id;
|
|
||||||
labelPopup.value = false
|
|
||||||
list.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索名字
|
|
||||||
const searchNameFn = () => {
|
|
||||||
// getMescroll().resetUpScroll();
|
|
||||||
if(searchName.value) redirect({ url: '/addon/shop/pages/goods/list', param: { goods_name: encodeURIComponent(searchName.value) } })
|
|
||||||
}
|
|
||||||
|
|
||||||
//点击商品购物车按钮
|
|
||||||
const cartRef = ref()
|
|
||||||
const itemCart = (row: any, id: any) => {
|
|
||||||
// 虚拟商品,并且需要核销,禁止加入购物车
|
|
||||||
if (row.goods_type == 'virtual' && row.virtual_receive_type == 'verify') {
|
|
||||||
return toLink(row.goodsSku.goods_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.cart.event !== 'cart') {
|
|
||||||
return toLink(row.goods_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({url: '/addon/shop/pages/goods/category'})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.goodsSku.sku_spec_format) {
|
|
||||||
cartRef.value.open(row.goodsSku.sku_id)
|
|
||||||
} else {
|
|
||||||
//单规格添加购物车
|
|
||||||
if (!row.goodsSku.stock || parseInt(row.goodsSku.num||0) > parseInt(row.goodsSku.stock)) {
|
|
||||||
uni.showToast({ title: '商品库存不足', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(row.min_buy && row.min_buy > parseInt(row.stock)){
|
|
||||||
uni.showToast({ title: '商品库存小于起购数量', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
animationAddCart(row, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//点击购物车加号 添加数量
|
|
||||||
const addCartBtn = (item: any, row: any, id: string) => {
|
|
||||||
if (parseInt(row.num) >= parseInt(row.stock)) {
|
|
||||||
uni.showToast({ title: '商品库存不足', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 起购
|
|
||||||
let num = row.num;
|
|
||||||
if(item.min_buy > 0 && item.min_buy > row.num){
|
|
||||||
num = item.min_buy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************** 限购-start *****************/
|
|
||||||
let maxBuyNum = -1;
|
|
||||||
// 限购 - 是否开启限购
|
|
||||||
if(item.is_limit && item.max_buy){
|
|
||||||
let max_buy = 0;
|
|
||||||
if(item.limit_type == 1){ //单次限购
|
|
||||||
max_buy = item.max_buy;
|
|
||||||
}else{ // 单人限购
|
|
||||||
let buyVal = item.max_buy - (item.has_buy||0);
|
|
||||||
max_buy = buyVal > 0 ? buyVal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(max_buy > item.goodsSku.stock){
|
|
||||||
maxBuyNum = item.goodsSku.stock
|
|
||||||
}else if(max_buy <= item.goodsSku.stock){
|
|
||||||
maxBuyNum = max_buy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(item.is_limit && num >= item.max_buy){
|
|
||||||
let tips = `该商品单次限购${item.max_buy}件`;
|
|
||||||
if(item.limit_type != 1){ //单次限购
|
|
||||||
tips = `该商品每人限购${item.max_buy}件`;
|
|
||||||
}
|
|
||||||
uni.showToast({ title: tips, icon: 'none' })
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/************** 限购-end *****************/
|
|
||||||
|
|
||||||
let obj = cloneDeep(item)
|
|
||||||
obj.num = num;
|
|
||||||
obj.id = row.id;
|
|
||||||
animationAddCart(obj, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
//点击购物车减号
|
|
||||||
const reduceCart = (data: any,row: any) => {
|
|
||||||
if(cartRepeatFlag.value) return false
|
|
||||||
cartRepeatFlag.value = true
|
|
||||||
|
|
||||||
let reduceNum = 1;
|
|
||||||
if(data.min_buy > 0 && data.min_buy == row.num){
|
|
||||||
reduceNum = data.min_buy;
|
|
||||||
}
|
|
||||||
|
|
||||||
cartStore.reduce({
|
|
||||||
id: row.id,
|
|
||||||
goods_id: row.goods_id,
|
|
||||||
sku_id: row.sku_id,
|
|
||||||
stock: row.stock,
|
|
||||||
sale_price: row.sale_price,
|
|
||||||
num: row.num
|
|
||||||
}, reduceNum, () => {
|
|
||||||
cartRepeatFlag.value = false
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//进入购物车
|
|
||||||
const toCart = () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/cart' })
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const isBindMobile = ref(uni.getStorageSync('isbindmobile'))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 结算
|
|
||||||
*/
|
|
||||||
const settlement = () => {
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
// 绑定手机号
|
|
||||||
if(uni.getStorageSync('isbindmobile')){
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
if (!totalNum.value) {
|
|
||||||
uni.showToast({ title: '还没有选择商品', icon: 'none' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const cart_ids: any = []
|
|
||||||
Object.values(cartList.value).forEach(item => {
|
|
||||||
Object.keys(item).forEach(v => {
|
|
||||||
if (v != 'totalNum' && v != 'totalMoney') cart_ids.push(item[v].id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
if(cart_ids.length == 0){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'orderCreateData',
|
|
||||||
data: { cart_ids },
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/payment' })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 价格类型
|
|
||||||
const priceType = (data:any) =>{
|
|
||||||
let type = "";
|
|
||||||
if(data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
type = 'member_price' // 会员价
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = (data:any) => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price) {
|
|
||||||
price = data.goodsSku.member_price ? data.goodsSku.member_price : data.goodsSku.price // 会员价
|
|
||||||
} else {
|
|
||||||
price = data.goodsSku.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.border-color {
|
|
||||||
border-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
height: 6rpx;
|
|
||||||
background-color: $u-primary;
|
|
||||||
width: 90%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-select {
|
|
||||||
position: relative;
|
|
||||||
margin-right: 28rpx;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background-color: #999;
|
|
||||||
width: 2rpx;
|
|
||||||
height: 70%;
|
|
||||||
top: 50%;
|
|
||||||
right: -14rpx;
|
|
||||||
transform: translatey(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.transform-rotate {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: $u-primary;
|
|
||||||
}
|
|
||||||
.border-color {
|
|
||||||
border-color: $u-primary;
|
|
||||||
}
|
|
||||||
.bg-color {
|
|
||||||
background-color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search input
|
|
||||||
.search-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt {
|
|
||||||
height: 58rpx;
|
|
||||||
background-color: #F6F8F8;
|
|
||||||
border-radius: 33rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-ipt .input-placeholder {
|
|
||||||
color: #A5A6A6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box {
|
|
||||||
width: 168rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-box .tab-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 56rpx;
|
|
||||||
padding: 20rpx 0;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
.tabs-box .tab-item-active {
|
|
||||||
position: relative;
|
|
||||||
color: var(--primary-color);
|
|
||||||
background-color:#f6f6f6;
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: '';
|
|
||||||
width: 6rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.category .labelPopup :deep(.u-transition) {
|
|
||||||
top: 92rpx !important;
|
|
||||||
left: 168rpx !important;
|
|
||||||
z-index: 8 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category .labelPopup.active :deep(.u-transition) {
|
|
||||||
top: 192rpx !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
.scroll-height{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
/* #ifdef H5 */
|
|
||||||
.cart{
|
|
||||||
.child.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.child.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.detail{
|
|
||||||
.child.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.child.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 50px - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 50px - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef H5 */
|
|
||||||
.cart{
|
|
||||||
.child.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.child.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.detail{
|
|
||||||
.child.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 92rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.child.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 92rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData1{
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 146rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
.noChild.noData2{
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - constant(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 40rpx - 100rpx - env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
.mescroll-empty.empty-page.part{
|
|
||||||
width: 542rpx;
|
|
||||||
height: 542rpx;
|
|
||||||
margin: 0;
|
|
||||||
padding-top: 50rpx;
|
|
||||||
.img{
|
|
||||||
width: 160rpx !important;
|
|
||||||
height: 120rpx !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,329 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-gray-100 min-h-[100vh]" :style="themeColor()">
|
|
||||||
<view class="fixed left-0 right-0 top-0 product-warp bg-[#fff]">
|
|
||||||
<view class="py-[14rpx] flex items-center justify-between px-[20rpx]">
|
|
||||||
<view class="flex-1 search-input mr-[20rpx]">
|
|
||||||
<text @click.stop="searchTypeFn('all')" class="nc-iconfont nc-icon-sousuo-duanV6xx1 btn"></text>
|
|
||||||
<input class="input" maxlength="50" type="text" v-model="goods_name" placeholder="请搜索您想要的商品" placeholderClass="text-[var(--text-color-light9)] text-[24rpx]" confirm-type="search" @confirm="searchTypeFn('all')">
|
|
||||||
<text v-if="goods_name" class="nc-iconfont nc-icon-cuohaoV6xx1 clear" @click="goods_name=''"></text>
|
|
||||||
</view>
|
|
||||||
<view :class="['iconfont text-[32rpx] text-[#333] -mb-[2rpx]', listType ? 'icona-yingyongzhongxinV6xx-32' : 'icona-yingyongliebiaoV6xx-32']" @click="listIconBtn"></view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between tems-center h-[88rpx] px-[30rpx]">
|
|
||||||
<view class=" flex items-center justify-between text-[26rpx] flex-1">
|
|
||||||
<text class="text-[#333]" :class="{ 'text-[var(--primary-color)] font-500': searchType == 'all' }" @click="searchTypeFn('all')">综合排序</text>
|
|
||||||
<view class="flex items-center text-[#333]" :class="{ 'text-[var(--primary-color)] font-500': searchType == 'sale_num' }" @click="searchTypeFn('sale_num')">
|
|
||||||
<text class="mr-[4rpx]">销量</text>
|
|
||||||
<text v-if="sale_num == 'asc'" class="text-[16rpx] nc-iconfont nc-icon-a-xiangshangV6xx1" :class="{'text-[var(--primary-color)]': searchType == 'sale_num' }"></text>
|
|
||||||
<text v-else class="text-[16rpx] nc-iconfont nc-icon-a-xiangxiaV6xx1" :class="{'text-[var(--primary-color)]': searchType == 'sale_num' }"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center text-[#333]" :class="{'text-[var(--primary-color)] font-500': searchType == 'price' }" @click="searchTypeFn('price')">
|
|
||||||
<text class="mr-[4rpx]">价格</text>
|
|
||||||
<text v-if="price == 'asc'" class="text-[16rpx] nc-iconfont nc-icon-a-xiangshangV6xx1" :class="{'text-[var(--primary-color)]': searchType == 'price' }"></text>
|
|
||||||
<text v-else class="text-[16rpx] nc-iconfont nc-icon-a-xiangxiaV6xx1" :class="{'text-[var(--primary-color)]': searchType == 'price' }"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center" :class="{'text-[var(--primary-color)] font-500': searchType == 'label', 'text-[#333]': searchType != 'label' }" @click="searchTypeFn('label')">
|
|
||||||
<text class="mr-[8rpx]">筛选</text>
|
|
||||||
<text class="iconfont font-500 icona-shaixuanV6xx-34 -mb-[4rpx] !text-[26rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<u-popup :show="labelPopup" mode="top" @close="labelPopup = false">
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<view class="text-[28rpx] px-[30rpx] mt-[40rpx]">全部分类</view>
|
|
||||||
<view class="flex flex-wrap pl-[30rpx] pt-[30rpx]">
|
|
||||||
<text @click="loadCategory(item.category_id)" v-for="(item, index) in categoryList" :key="item.category_id"
|
|
||||||
:class="{ 'label-select': currGoodsCategory == item.category_id }" class="truncate text-[#333] px-[10rpx] border-[2rpx] border-solid border-transparent w-[184rpx] h-[56rpx] flex items-center justify-center mr-[30rpx] mb-[30rpx] box-border bg-[var(--temp-bg)] rounded-[50rpx] text-[24rpx]">
|
|
||||||
{{ item.category_name }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
|
|
||||||
<mescroll-body ref="mescrollRef" top="176rpx" bottom="60px" @init="mescrollInit" :down="{ use: false }" @up="getAllAppListFn">
|
|
||||||
<view v-if="goodsList.length" :class="['sidebar-margin', !listType ? 'biserial-goods-list' : '']">
|
|
||||||
<template v-if="listType">
|
|
||||||
<view v-for="(item, index) in goodsList" :key="index" class="bg-white flex px-[20rpx] py-[24rpx] rounded-[var(--rounded-small)] overflow-hidden top-mar" :class="{ 'mb-[20rpx]': (index+1) == goodsList.length}" @click="toDetail(item.goods_id)">
|
|
||||||
<image v-if="item.goods_cover_thumb_mid" class="w-[190rpx] h-[190rpx] rounded-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[190rpx] h-[190rpx] rounded-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
<view class="flex-1 flex flex-col ml-[20rpx] py-[6rpx]">
|
|
||||||
<view class="text-[28rpx] text-[#333] leading-[40rpx] multi-hidden mb-[10rpx]">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="mt-auto flex justify-between items-baseline">
|
|
||||||
<view class="flex items-baseline mt-[20rpx]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font flex items-baseline">
|
|
||||||
<text class="text-[24rpx] font-500 mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text class="text-[22rpx] mt-[20rpx] text-[var(--text-color-light9)]">已售{{ item.sale_num }}{{ item.unit }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<view>
|
|
||||||
<template v-for="(item, index) in goodsList">
|
|
||||||
<view v-if="(index%2) == 0" class="flex flex-col bg-[#fff] box-border rounded-[var(--rounded-mid)] overflow-hidden mt-[var(--top-m)]" @click="toDetail(item.goods_id)">
|
|
||||||
<image v-if="item.goods_cover_thumb_mid" class="w-[100%] h-[344rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[100%] h-[344rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
<view class="px-[20rpx] flex-1 pt-[16rpx] pb-[24rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#303133] leading-[40rpx] text-[28rpx] multi-hidden">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-end">
|
|
||||||
<view class="flex items-baseline mt-[20rpx]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font flex items-baseline">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text class="text-[22rpx] text-[var(--text-color-light9)] mt-[20rpx]">已售{{ item.sale_num }}{{ item.unit}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<template v-for="(item, index) in goodsList">
|
|
||||||
<view v-if="(index%2) == 1" class="flex flex-col bg-[#fff] box-border rounded-[var(--rounded-mid)] overflow-hidden mt-[var(--top-m)]" @click="toDetail(item.goods_id)">
|
|
||||||
<image v-if="item.goods_cover_thumb_mid" class="w-[100%] h-[344rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[100%] h-[344rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
<view class="px-[20rpx] flex-1 pt-[16rpx] pb-[24rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[#303133] leading-[40rpx] text-[28rpx] multi-hidden">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-baseline">
|
|
||||||
<view class="flex items-baseline mt-[20rpx]">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font flex items-baseline">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<image v-if="diyGoods.priceType(item) == 'member_price'" class="max-w-[50rpx] h-[28rpx] ml-[6rpx]" :src="img('addon/shop/VIP.png')" mode="heightFix" />
|
|
||||||
</view>
|
|
||||||
<text class="mt-[20rpx] text-[22rpx] text-[var(--text-color-light9)]">已售{{ item.sale_num }}{{ item.unit}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!goodsList.length && loading" :option="{tip : '暂无商品', btnText:'去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/index', mode: 'reLaunch' })"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
|
|
||||||
<tabbar />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, onMounted } from 'vue'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect, img, getToken } from '@/utils/common';
|
|
||||||
import { getGoodsCategoryTree, getGoodsPages } from '@/addon/shop/api/goods';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const categoryList = ref<Array<Object>>([]);
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
const coupon_id = ref<number | string>('');
|
|
||||||
const currGoodsCategory = ref<number | string>('');
|
|
||||||
const mescrollRef = ref(null);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
// 标签
|
|
||||||
const labelPopup = ref(false);
|
|
||||||
const goods_name = ref("");
|
|
||||||
const price = ref("");
|
|
||||||
const sale_num = ref("");
|
|
||||||
const searchType = ref('all');
|
|
||||||
const isShow = ref(false)//输入框清除文字按钮
|
|
||||||
//列表类型
|
|
||||||
const listType = ref(true)
|
|
||||||
onLoad(async (option: any) => {
|
|
||||||
currGoodsCategory.value = option.curr_goods_category || ''
|
|
||||||
goods_name.value = option.goods_name ? decodeURIComponent(option.goods_name) : ''
|
|
||||||
coupon_id.value = option.coupon_id || ''
|
|
||||||
await getGoodsCategoryTree().then((res: any) => {
|
|
||||||
const initData = { category_name: "全部", category_id: '' };
|
|
||||||
categoryList.value.push(initData);
|
|
||||||
categoryList.value = categoryList.value.concat(res.data);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllAppListFn = (mescroll: mescrollStructure) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
goods_category: currGoodsCategory.value,
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
keyword: goods_name.value,
|
|
||||||
coupon_id: coupon_id.value,
|
|
||||||
order: searchType.value === 'all' ? '' : searchType.value,
|
|
||||||
sort: searchType.value == 'price' ? price.value : sale_num.value
|
|
||||||
};
|
|
||||||
getGoodsPages(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (Number(mescroll.num) === 1) {
|
|
||||||
goodsList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
goodsList.value = goodsList.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadCategory = (id: string) => {
|
|
||||||
currGoodsCategory.value = id;
|
|
||||||
goodsList.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
labelPopup.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索
|
|
||||||
const searchTypeFn = (type: any) => {
|
|
||||||
searchType.value = type;
|
|
||||||
if (type == 'all') {
|
|
||||||
sale_num.value = '';
|
|
||||||
price.value = '';
|
|
||||||
}
|
|
||||||
if (type == 'price') {
|
|
||||||
sale_num.value = '';
|
|
||||||
if (price.value) {
|
|
||||||
price.value = price.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
} else {
|
|
||||||
price.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == 'sale_num') {
|
|
||||||
price.value = '';
|
|
||||||
if (sale_num.value) {
|
|
||||||
sale_num.value = sale_num.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
} else {
|
|
||||||
sale_num.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == 'label') {
|
|
||||||
sale_num.value = 'asc';
|
|
||||||
price.value = 'asc';
|
|
||||||
labelPopup.value = true;
|
|
||||||
} else {
|
|
||||||
labelPopup.value = false;
|
|
||||||
goodsList.value = [];
|
|
||||||
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//列表样式切换
|
|
||||||
const listIconBtn = () => {
|
|
||||||
listType.value = !listType.value
|
|
||||||
}
|
|
||||||
const toDetail = (id: string | number) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { goods_id: id }, mode: 'navigateTo' })
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
getMescroll().optUp.textNoMore = t("end");
|
|
||||||
}, 500)
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
.scroll-view-wrap {
|
|
||||||
word-break: keep-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-select {
|
|
||||||
color: var(--primary-color);
|
|
||||||
border-color: var(--primary-color);
|
|
||||||
background-color: var(--primary-color-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-popup .u-transition) {
|
|
||||||
top: 156rpx !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-warp {
|
|
||||||
z-index: 99999;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-bar-placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar__placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
:deep(.u-input__content__clear){
|
|
||||||
width: 28rpx;
|
|
||||||
height: 28rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
background-color: var(--text-color-light9);
|
|
||||||
}
|
|
||||||
.biserial-goods-list{
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-gap: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,311 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="min-h-[100vh]" :style="themeColor()">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<top-tabbar :data="param" :isFill="false"/>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- 顶部图片 -->
|
|
||||||
<view class="rank-head">
|
|
||||||
<image class="w-[100%] h-[435rpx]" :src="img(rankConfig.rank_images)" mode="aspectFill"></image>
|
|
||||||
<view class="content-box">
|
|
||||||
<!-- 榜单分类按钮 -->
|
|
||||||
<scroll-view scroll-x="true" class="category-slider" scroll-with-animation :scroll-into-view="'id' + activeIndex">
|
|
||||||
<view class="category-con" :style="rankList.length <= 3 ? { display: 'flex', justifyContent: 'center' } : {}">
|
|
||||||
<view class="category-btn" v-for="(item, index) in rankList" :key="index" :id="'id' + index" @click="selectCategory(item, index)" :style="{ color: activeIndex === index ? rankConfig.select_color : rankConfig.no_color, background: activeIndex === index ? `linear-gradient(to right, ${rankConfig.select_bg_color_start}, ${rankConfig.select_bg_color_end})`: 'transparent'}">
|
|
||||||
<view>{{ item.name }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</scroll-view>
|
|
||||||
<!-- <view class="content">
|
|
||||||
<text class="text-[26rpx]">{{rankConfig.rank_name}}</text>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
|
||||||
<view class="side-tab" :style="{ top: topStyle }" @click="rankPopup = true" v-if="rankConfig.rank_remark">
|
|
||||||
<text class="iconfont icona-paihangbangpc30 icon"></text>
|
|
||||||
<text class="desc">{{t('rankingRules')}}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="rank-list p-[20rpx] relative -mt-[42rpx]">
|
|
||||||
|
|
||||||
<!-- 列表 -->
|
|
||||||
<mescroll-body ref="mescrollRef" :height="listHeight" @init="mescrollInit" :down="{ use: false }" @up="getRankGoodsListFn">
|
|
||||||
<view class="bg-[#fff] flex rounded-[var(--rounded-mid)] p-[20rpx]" v-for="(item,index) in rankGoodsList" :key="item.goods_id" :class="{'mb-[20rpx]': (rankGoodsList.length-1) != index}" v-if="rankGoodsList.length" @click="toLink(item.goods_id)">
|
|
||||||
<view class="w-[240rpx] h-[240rpx] flex items-center justify-center relative">
|
|
||||||
<!-- 榜单排名图片 -->
|
|
||||||
<image v-if="index < 5" class="absolute top-[7rpx] left-[10rpx] w-[50rpx] h-[58rpx]" :style="{ zIndex:9 }" :src="getRankBadge(item.rank_num)" mode="aspectFill"></image>
|
|
||||||
<view class="absolute top-[15rpx] left-[10rpx] flex items-center justify-center w-[50rpx] h-[50rpx]" v-if="index < 5" :style="{ zIndex: 10 }">
|
|
||||||
<text class="text-[24rpx] font-bold text-[#fff]">{{ index + 1 }}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<image v-if="item.goods_cover_thumb_mid" class="w-[250rpx] h-[250rpx] rounded-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image class="w-[240rpx] h-[240rpx] rounded-[var(--rounded-mid)]" v-else :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col flex-1 justify-between ml-[20rpx] pt-[4rpx]">
|
|
||||||
<view class="text-[28rpx] text-[#333] leading-[40rpx] multi-hidden mb-[10rpx]">
|
|
||||||
<view class="brand-tag" v-if="item.goods_brand">
|
|
||||||
{{item.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{ item.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.goods_label_name && item.goods_label_name.length" class="flex flex-wrap">
|
|
||||||
<template v-for="(tagItem, tagIndex) in item.goods_label_name">
|
|
||||||
<image class="img-tag" v-if="tagItem.style_type == 'icon' && tagItem.icon" :src="img(tagItem.icon)" mode="heightFix" @error="diyGoods.error(tagItem,'icon')"></image>
|
|
||||||
<view class="base-tag" v-else-if="tagItem.style_type == 'diy' || !tagItem.icon" :style="diyGoods.baseTagStyle(tagItem)">
|
|
||||||
{{tagItem.label_name}}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font flex items-baseline">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ diyGoods.goodsPrice(item).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<view :id="'itemCart' + index" class="w-[102rpx] box-border text-center text-[#fff] primary-btn-bg h-[46rpx] text-[22rpx] leading-[46rpx] rounded-[100rpx]">去购买</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!rankGoodsList.length && loading" :option="{tip : '暂无商品', btnText:'去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/goods/list'})"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup :show="rankPopup" @close="closeFn" mode="center" round="var(--rounded-big)">
|
|
||||||
<view class="w-[570rpx] px-[32rpx] popup-common center">
|
|
||||||
<view class="title">{{t('rankingRules')}}</view>
|
|
||||||
<scroll-view :scroll-y="true" class="px-[30rpx] box-border max-h-[260rpx]">
|
|
||||||
<view class="text-[28rpx] leading-[40rpx] mb-[20rpx]">{{rankConfig.rank_remark}}</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap !pt-[40rpx]">
|
|
||||||
<button class="primary-btn-bg w-[480rpx] h-[70rpx] text-[26rpx] leading-[70rpx] rounded-[35rpx] !text-[#fff] font-500" @click="rankPopup = false">我知道了</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, computed } from 'vue'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect, img, pxToRpx } from '@/utils/common';
|
|
||||||
import { getRankList ,getRankGoodsList,getRankConfig} from '@/addon/shop/api/rank';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import { useGoods } from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const mescrollRef = ref(null);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
// 获取系统状态栏的高度
|
|
||||||
let menuButtonInfo : any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let param = topTabarObj.setTopTabbarParam({ title: '' })
|
|
||||||
const topStyle = computed(() => {
|
|
||||||
let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 30 + 'rpx;'
|
|
||||||
return style
|
|
||||||
})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
// 获取系统信息
|
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
|
||||||
const topImageHeight = 450;
|
|
||||||
const screenHeight = systemInfo.windowHeight;
|
|
||||||
// 将屏幕高度转换为 rpx
|
|
||||||
const screenHeightInRpx = (screenHeight / systemInfo.screenWidth) * 750;
|
|
||||||
// 计算列表高度
|
|
||||||
const listHeight = computed(() => {
|
|
||||||
const listHeightValue = screenHeightInRpx - topImageHeight;
|
|
||||||
return `${listHeightValue}rpx`;
|
|
||||||
});
|
|
||||||
/**************** 榜单规则 ********************/
|
|
||||||
const rankPopup = ref(false)
|
|
||||||
const closeFn = () =>{
|
|
||||||
rankPopup.value = false
|
|
||||||
}
|
|
||||||
const rankList = ref<Array<any>>([]);
|
|
||||||
const rankGoodsList = ref<Array<any>>([]);
|
|
||||||
|
|
||||||
// 加载分类数据
|
|
||||||
const getRankListFn = (isFirstLoad = false) => {
|
|
||||||
getRankList().then((res) => {
|
|
||||||
rankList.value = res.data
|
|
||||||
|
|
||||||
// 仅在首次加载时选择第一个分类
|
|
||||||
if (isFirstLoad && rankList.value && rankList.value.length) {
|
|
||||||
selectCategory(rankList.value[0], 0);
|
|
||||||
} else if (!rankList.value.length) {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error("加载分类数据失败", error);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const rankConfig = reactive({});
|
|
||||||
|
|
||||||
// 榜单设置
|
|
||||||
const getRankConfigFn = () => {
|
|
||||||
getRankConfig().then((res: any) => {
|
|
||||||
Object.assign(rankConfig, res.data); // 合并新数据
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 当前选中的分类的索引
|
|
||||||
const activeIndex = ref(0)
|
|
||||||
// 当前选中的分类的rank_id
|
|
||||||
const rankId = ref(0)
|
|
||||||
// 当前选中的分类的goods_source
|
|
||||||
const goodsSource = ref()
|
|
||||||
// 点击分类按钮时,更新选中的分类
|
|
||||||
function selectCategory(rank:any, index:any) {
|
|
||||||
loading.value = false;
|
|
||||||
// 清空之前选中的商品列表
|
|
||||||
rankGoodsList.value = [];
|
|
||||||
activeIndex.value = index
|
|
||||||
rankId.value = rank.rank_id
|
|
||||||
goodsSource.value = rank.goods_source
|
|
||||||
getMescroll()?.resetUpScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取榜单商品
|
|
||||||
const getRankGoodsListFn = (mescroll: any) => {
|
|
||||||
if(rankList.value.length == 0) return;
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
rank_id:rankId.value
|
|
||||||
};
|
|
||||||
|
|
||||||
getRankGoodsList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>).map((el: any) => {return el})
|
|
||||||
let ifPage = true
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
rankGoodsList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
rankGoodsList.value = rankGoodsList.value.concat(newArr);
|
|
||||||
if(goodsSource.value=='goods'){
|
|
||||||
ifPage = false
|
|
||||||
}else{
|
|
||||||
ifPage = true
|
|
||||||
}
|
|
||||||
mescroll.endSuccess(newArr.length,ifPage);
|
|
||||||
|
|
||||||
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 跳转商品详情
|
|
||||||
const toLink = (goods_id: any) => {
|
|
||||||
redirect({url:'/addon/shop/pages/goods/detail',param:{ goods_id }})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取排行榜名次图片的函数
|
|
||||||
function getRankBadge(sort:any) {
|
|
||||||
switch (sort) {
|
|
||||||
case 1:
|
|
||||||
return img('addon/shop/rank/rank_first.png');
|
|
||||||
case 2:
|
|
||||||
return img('addon/shop/rank/rank_second.png');
|
|
||||||
case 3:
|
|
||||||
return img('addon/shop/rank/rank_third.png');
|
|
||||||
default:
|
|
||||||
return img('addon/shop/rank/rank.png');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad(async (option : any) => {
|
|
||||||
getRankConfigFn()
|
|
||||||
getRankListFn(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
|
|
||||||
.rank-head {
|
|
||||||
position: relative;
|
|
||||||
.content-box{
|
|
||||||
width: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 328rpx;
|
|
||||||
.category-slider {
|
|
||||||
width: 95%;
|
|
||||||
margin: 0 auto;
|
|
||||||
line-height: 100rpx;
|
|
||||||
white-space: nowrap;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
.category-con{
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.category-btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 20rpx;
|
|
||||||
height: 55rpx;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 55rpx;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 40rpx;
|
|
||||||
font-size: 24rpx;
|
|
||||||
margin-right: 20rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// .content {
|
|
||||||
// display: flex;
|
|
||||||
// justify-content: center;
|
|
||||||
// align-items: center;
|
|
||||||
// border-radius: 30rpx;
|
|
||||||
// padding: 0 20rpx;
|
|
||||||
// height: 44rpx;
|
|
||||||
// font-size: 26rpx;
|
|
||||||
// color: var(--primary-color);
|
|
||||||
// background: linear-gradient(to right, #FFEBD7, #FFFFFF, #FFEBD7);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.rank-list {
|
|
||||||
background: #F8F8F8;
|
|
||||||
border-radius: 34rpx 34rpx 0 0;
|
|
||||||
|
|
||||||
.bank-buying {
|
|
||||||
width: 100rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
font-family: PingFang SC, PingFang SC;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #FFFFFF;
|
|
||||||
line-height: 44rpx;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="flex items-center px-[20rpx] h-[120rpx]">
|
|
||||||
<view class="h-[68rpx] bg-[var(--temp-bg)] px-[30rpx] flex items-center rounded-[100rpx] flex-1">
|
|
||||||
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[var(--text-color-light9)] text-[26rpx] mr-[18rpx]"></text>
|
|
||||||
<input class="text-[28rpx] flex-1" maxlength="50" type="text" v-model="inputValue" placeholder="请搜索您想要的商品" confirm-type="search" placeholderClass="text-[var(--text-color-light9)] text-[28rpx]" @confirm="search">
|
|
||||||
<text v-if="inputValue" class="nc-iconfont nc-icon-cuohaoV6xx1 text-[24rpx] text-[var(--text-color-light9)]" @click="inputValue=''"></text>
|
|
||||||
</view>
|
|
||||||
<text @click.stop="search()" class="text-[26rpx] ml-[32rpx] -mb-[2rpx]">搜索</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="search-content">
|
|
||||||
<!-- 历史搜索 -->
|
|
||||||
<view class="history" v-if="historyList.length">
|
|
||||||
<view class="history-box">
|
|
||||||
<view class="history-top">
|
|
||||||
<view class="title font-500">历史搜索</view>
|
|
||||||
<view class="icon nc-iconfont nc-icon-shanchu-yuangaizhiV6xx !text-[24rpx] text-[var(--text-color-light6)]" @click="deleteHistoryList"></view>
|
|
||||||
</view>
|
|
||||||
<view class="history-bottom " id="history-list" :style="{ maxHeight: !isAllHistory ? '100%' : '148rpx' }">
|
|
||||||
<block v-for="(item, index) in historyList" :key="index">
|
|
||||||
<view class="history-li" @click="otherSearch(item)" v-if="item">
|
|
||||||
<view>{{ item }}</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<view class="history-li history_more" v-if="isAllHistory" @click="isAllHistory = false">
|
|
||||||
<view class="content-box">
|
|
||||||
<text class="text-[30rpx] nc-iconfont nc-icon-xiaV6xx"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
||||||
import { ref, nextTick } from 'vue';
|
|
||||||
import { redirect } from '@/utils/common';
|
|
||||||
import useConfigStore from "@/stores/config";
|
|
||||||
|
|
||||||
const inputValue = ref('') //搜索框的值
|
|
||||||
const historyList = ref([]) //历史搜索记录
|
|
||||||
const isAllHistory = ref(false)
|
|
||||||
|
|
||||||
onLoad((options:any) => {
|
|
||||||
uni.getStorageSync('goodsSearchHistory') ? '' : uni.setStorageSync('goodsSearchHistory', []);
|
|
||||||
});
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
findHistoryList()
|
|
||||||
nextTick(()=> {
|
|
||||||
getHistoryHeight();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
//获取历史搜索记录
|
|
||||||
const findHistoryList =()=> {
|
|
||||||
historyList.value = uni.getStorageSync('goodsSearchHistory').reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除所有历史记录
|
|
||||||
const deleteHistoryList =()=> {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '确认删除全部历史记录?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
uni.setStorageSync('goodsSearchHistory', []);
|
|
||||||
findHistoryList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//搜索
|
|
||||||
const search = ()=> {
|
|
||||||
// if (inputValue.value.trim() != '') {
|
|
||||||
|
|
||||||
// 对历史搜索处理,判断有无,最近搜索显示在最前
|
|
||||||
let historyList = uni.getStorageSync('goodsSearchHistory');
|
|
||||||
let array = [];
|
|
||||||
if (historyList.length) {
|
|
||||||
array = historyList.filter(v => {
|
|
||||||
return v != inputValue.value.trim();
|
|
||||||
});
|
|
||||||
array.push(inputValue.value.trim());
|
|
||||||
} else {
|
|
||||||
array.push(inputValue.value.trim());
|
|
||||||
}
|
|
||||||
uni.setStorageSync('goodsSearchHistory', array);
|
|
||||||
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/list', param: { goods_name: encodeURIComponent(inputValue.value) }, mode: 'navigateTo' })
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 点击历史搜索
|
|
||||||
const otherSearch = (e:any)=> {
|
|
||||||
inputValue.value = e;
|
|
||||||
search();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取元素高度
|
|
||||||
const getHistoryHeight =()=> {
|
|
||||||
const query = uni.createSelectorQuery().in(this);
|
|
||||||
query.select('#history-list').boundingClientRect((data: any) => {
|
|
||||||
if (data && data.height > uni.upx2px(70) * 2 + uni.upx2px(35) * 2) {
|
|
||||||
isAllHistory.value = true;
|
|
||||||
}
|
|
||||||
}).exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.content {
|
|
||||||
width: 100vw;
|
|
||||||
/* #ifdef MP */
|
|
||||||
height: 100vh;
|
|
||||||
/* #endif */
|
|
||||||
/* #ifdef H5 */
|
|
||||||
height: calc(100vh - env(safe-area-inset-bottom) - var(--status-bar-height));
|
|
||||||
height: calc(100vh - constant(safe-area-inset-bottom) - var(--status-bar-height));
|
|
||||||
/* #endif */
|
|
||||||
/* #ifdef APP-PLUS */
|
|
||||||
height: calc(100vh - 44px - env(safe-area-inset-bottom));
|
|
||||||
height: calc(100vh - 44px - constant(safe-area-inset-bottom));
|
|
||||||
/* #endif */
|
|
||||||
background: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-content {
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.history {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.history-box {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: #ffffff;
|
|
||||||
padding: 16rpx 20rpx 0rpx 20rpx;
|
|
||||||
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.history-top {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
color: var(--text-color-light9);
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-bottom {
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 20rpx;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.history-li {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 20rpx;
|
|
||||||
margin-bottom: 15rpx;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
view {
|
|
||||||
line-height: 56rpx;
|
|
||||||
background: var(--temp-bg) !important;
|
|
||||||
height: 56rpx;
|
|
||||||
color: #333 !important;
|
|
||||||
margin: 0 0rpx 4rpx 0 !important;
|
|
||||||
padding: 0 24rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
border-radius: 100rpx;
|
|
||||||
font-size: 24rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.history_more {
|
|
||||||
margin-right: 0;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
.content-box{
|
|
||||||
box-shadow: 2rpx 2rpx 8rpx rgba(0,0,0,.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
|
|
||||||
<loading-page :loading="diy.getLoading()"></loading-page>
|
|
||||||
|
|
||||||
<view v-show="!diy.getLoading()">
|
|
||||||
|
|
||||||
<!-- 自定义模板渲染 -->
|
|
||||||
<view class="diy-template-wrap bg-index" v-if="diy.data.pageMode != 'fixed'" :style="diy.pageStyle()">
|
|
||||||
|
|
||||||
<diy-group ref="diyGroupRef" :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 固定模板渲染 -->
|
|
||||||
<view class="fixed-template-wrap" v-if="diy.data.pageMode == 'fixed'">
|
|
||||||
|
|
||||||
<fixed-group :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref,nextTick } from 'vue';
|
|
||||||
import {useDiy} from '@/hooks/useDiy'
|
|
||||||
import diyGroup from '@/addon/components/diy/group/index.vue'
|
|
||||||
import fixedGroup from '@/addon/components/fixed/group/index.vue'
|
|
||||||
|
|
||||||
const diy = useDiy({
|
|
||||||
name: 'DIY_SHOP_INDEX'
|
|
||||||
})
|
|
||||||
|
|
||||||
const diyGroupRef = ref(null)
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
// 监听页面加载
|
|
||||||
diy.onLoad();
|
|
||||||
|
|
||||||
// 监听页面显示
|
|
||||||
diy.onShow((data: any) => {
|
|
||||||
diyGroupRef.value?.refresh();
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听页面隐藏
|
|
||||||
diy.onHide();
|
|
||||||
|
|
||||||
// 监听页面卸载
|
|
||||||
diy.onUnload();
|
|
||||||
|
|
||||||
// 监听下拉刷新事件
|
|
||||||
diy.onPullDownRefresh()
|
|
||||||
|
|
||||||
// 监听滚动事件
|
|
||||||
diy.onPageScroll()
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/styles/diy.scss';
|
|
||||||
</style>
|
|
||||||
<style lang="scss">
|
|
||||||
.diy-template-wrap {
|
|
||||||
/* #ifdef MP */
|
|
||||||
.child-diy-template-wrap {
|
|
||||||
::v-deep .diy-group {
|
|
||||||
> .draggable-element.top-fixed-diy {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
|
|
||||||
<loading-page :loading="diy.getLoading()"></loading-page>
|
|
||||||
|
|
||||||
<view v-show="!diy.getLoading()">
|
|
||||||
|
|
||||||
<!-- 自定义模板渲染 -->
|
|
||||||
<view class="diy-template-wrap bg-index" v-if="diy.data.pageMode != 'fixed'" :style="diy.pageStyle()">
|
|
||||||
|
|
||||||
<diy-group ref="diyGroupRef" :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 固定模板渲染 -->
|
|
||||||
<view class="fixed-template-wrap" v-if="diy.data.pageMode == 'fixed'">
|
|
||||||
|
|
||||||
<fixed-group :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import {ref, computed,nextTick} from 'vue';
|
|
||||||
import {useDiy} from '@/hooks/useDiy'
|
|
||||||
import diyGroup from '@/addon/components/diy/group/index.vue'
|
|
||||||
import fixedGroup from '@/addon/components/fixed/group/index.vue'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
|
|
||||||
// 会员信息
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
const diy = useDiy({
|
|
||||||
name: 'DIY_SHOP_MEMBER_INDEX'
|
|
||||||
})
|
|
||||||
|
|
||||||
const diyGroupRef = ref(null)
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
// 监听页面加载
|
|
||||||
diy.onLoad();
|
|
||||||
|
|
||||||
// 监听页面显示
|
|
||||||
diy.onShow((data: any) => {
|
|
||||||
diyGroupRef.value?.refresh();
|
|
||||||
if (userInfo.value) {
|
|
||||||
useMemberStore().getMemberInfo()
|
|
||||||
}
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听页面隐藏
|
|
||||||
diy.onHide();
|
|
||||||
|
|
||||||
// 监听页面卸载
|
|
||||||
diy.onUnload();
|
|
||||||
|
|
||||||
// 监听下拉刷新事件
|
|
||||||
diy.onPullDownRefresh()
|
|
||||||
|
|
||||||
// 监听滚动事件
|
|
||||||
diy.onPageScroll()
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/styles/diy.scss';
|
|
||||||
</style>
|
|
||||||
<style lang="scss">
|
|
||||||
.diy-template-wrap {
|
|
||||||
/* #ifdef MP */
|
|
||||||
.child-diy-template-wrap {
|
|
||||||
::v-deep .diy-group {
|
|
||||||
> .draggable-element.top-fixed-diy {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[#f8f8f8] min-h-screen overflow-hidden" :style="themeColor()" v-if="memberStore.info">
|
|
||||||
<view class="fixed left-0 top-0 right-0 z-10">
|
|
||||||
<scroll-view :scroll-x="true" class="scroll-Y box-border px-[var(--sidebar-m)] bg-white">
|
|
||||||
<view class="flex whitespace-nowrap justify-around items-center h-[88rpx]">
|
|
||||||
<view :class="['text-[28rpx] text-[#333] h-[88rpx] leading-[88rpx] font-400', { 'class-select !text-primary': couponStatus === item.status }]" @click="statusClickFn(item.status)" v-for="(item, index) in statusList">{{ item.status_name }}({{ item.count }})</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="'id' + (subActive ? subActive - 1 : 0)" class="px-[var(--sidebar-m)] box-border bg-white">
|
|
||||||
<view class="items-center flex h-[88rpx]">
|
|
||||||
<text class="flex-shrink-0 w-[126rpx] h-[54rpx] text-[24rpx] flex-center text-center text-[#333] bg-[var(--temp-bg)] rounded-[30rpx] box-border mr-[20rpx] border-[2rpx] border-solid border-[#F8F9FD]" :class="{'!text-primary !border-primary font-500 !bg-[var(--primary-color-light)]':item.value == curType}"
|
|
||||||
v-for="(item,index) in typeList" :key="index" :id="'id' + index"
|
|
||||||
@click="typeClick(index,item.value)">{{item.label}}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<mescroll-body ref="mescrollRef" top="176rpx" @init="mescrollInit" :down="{ use: false }" @up="getMyCouponListFn">
|
|
||||||
<view class="py-[var(--top-m)] px-[var(--sidebar-m)]" v-if="list.length">
|
|
||||||
<template v-for="(item, index) in list">
|
|
||||||
|
|
||||||
<view v-if="couponStatus != 1"
|
|
||||||
class="flex items-center relative w-[100%] rounded-[var(--rounded-small)] overflow-hidden bg-[#fff]" :class="{'mt-[var(--top-m)]':index}">
|
|
||||||
<view class=" w-[186rpx] h-[160rpx] flex flex-col items-center justify-center rounded-[var(--rounded-small)] relative coupon-item" :class="{'bg-[#ffb4b1]':couponStatus == 2 , 'bg-[#ffe2e4]' :couponStatus == 3}">
|
|
||||||
<view class="price-font flex items-baseline" :class="{'text-[#fff]' : couponStatus == 2 , 'text-[#FFB4B1]' : couponStatus == 3}">
|
|
||||||
<text class="text-[30rpx] leading-[34rpx] mr-[2rpx] text-center price-font font-500">¥</text>
|
|
||||||
<text class="text-[54rpx] font-500 leading-[58rpx] price-font truncate">{{ item.coupon_price }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="truncate max-w-[176rpx] mt-[6rpx] text-[24rpx] h-[32rpx] leading-[32rpx]" :class="{'text-[#fff]': couponStatus == 2 , 'text-[#FFB4B1]': couponStatus == 3}">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[30rpx] flex-1 h-[100%] box-border py-[20rpx]">
|
|
||||||
<view class="text-[26rpx] leading-[40rpx] text-left font-500">
|
|
||||||
<text v-if="item.min_condition_money === '0.00'">无门槛</text>
|
|
||||||
<text v-else>满{{ item.coupon_min_price }}元可用</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx] flex items-center">
|
|
||||||
<text class="w-[80rpx] text-center bg-[#FFEFF0] whitespace-nowrap text-[#EF000C] text-[18rpx] h-[30rpx] leading-[30rpx] rounded-[15rpx] mr-[10rpx] flex-shrink-0">{{ item.type_name }}</text>
|
|
||||||
<text class="truncate max-w-[226rpx] text-[24rpx] text-[var(--text-color-light6)] leading-[34rpx]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[100%] mt-[6rpx] text-[20rpx] leading-[34rpx] text-[var(--text-color-light6)]">
|
|
||||||
<text>有效期至<text>{{ item.expire_time ? item.expire_time.slice(0, 10) : '' }}</text></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="px-[20rpx]">
|
|
||||||
<button class="flex-center rounded-full remove-border" :style="{width:'150rpx',height:'60rpx',color:'#fff', fontSize:'24rpx', padding:'0',border:'none',backgroundColor:'#FFB4B1'}" v-if="couponStatus == 2">已使用</button>
|
|
||||||
<button class="flex-center rounded-full remove-border" :style="{width:'150rpx',height:'60rpx',color:'#FFB4B1', fontSize:'24rpx', padding:'0',border:'none',backgroundColor:'#FFE2E4'}" v-if="couponStatus == 3">已过期</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center relative w-[100%] rounded-[var(--rounded-small)] overflow-hidden bg-[#fff]" :class="{'mt-[var(--top-m)]' : index}">
|
|
||||||
<view class="coupon-bg w-[186rpx] h-[160rpx] flex flex-col items-center justify-center rounded-[var(--rounded-small)] relative coupon-item">
|
|
||||||
<view class="price-font flex items-baseline text-[#fff]">
|
|
||||||
<text class="text-[30rpx] leading-[34rpx] mr-[2rpx] text-center price-font font-500">¥</text>
|
|
||||||
<text class="text-[54rpx] font-500 leading-[58rpx] price-font truncate">{{ item.coupon_price }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="truncate max-w-[176rpx] mt-[6rpx] text-[22rpx] text-[#fff] h-[32rpx] leading-[32rpx]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[30rpx] flex-1 h-[100%] box-border py-[20rpx]">
|
|
||||||
<view class="text-[26rpx] leading-[40rpx] text-left font-500">
|
|
||||||
<text v-if="item.min_condition_money === '0.00'">无门槛</text>
|
|
||||||
<text v-else>满{{ item.coupon_min_price }}元可用</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[20rpx] mt-[10rpx] flex items-center">
|
|
||||||
<text class="w-[80rpx] text-center bg-[#FFEFF0] whitespace-nowrap text-[#EF000C] text-[18rpx] h-[30rpx] leading-[30rpx] rounded-[15rpx] mr-[10rpx] flex-shrink-0">{{ item.type_name }}</text>
|
|
||||||
<text class="truncate max-w-[226rpx] text-[24rpx] text-[var(--text-color-light9)] leading-[34rpx]">{{ item.title }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="w-[100%] mt-[6rpx] text-[20rpx] leading-[34rpx] text-[var(--text-color-light9)]">
|
|
||||||
<text>有效期至<text>{{ item.expire_time ? item.expire_time.slice(0, 10) : '' }}</text></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="px-[20rpx]" v-if="couponStatus === 1">
|
|
||||||
<button hover-class="none" class="flex-center rounded-full remove-border primary-btn-bg" :style="{width:'150rpx',height:'60rpx',color:'#fff', fontSize:'24rpx', padding:'0',border:'none'}" @click="toLink(item.coupon_id)">去使用</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!list.length && loading" :option="{'tip' : '暂无优惠券'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<pay ref="payRef"></pay>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { img, redirect } from '@/utils/common'
|
|
||||||
import { getMyCouponList, getMyCouponType, getMyCouponStatusCount } from '@/addon/shop/api/coupon'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
|
|
||||||
import { onLoad,onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const statusList = ref<Array<Object>>([]);
|
|
||||||
const couponStatus = ref(1);
|
|
||||||
|
|
||||||
const getMyCouponStatusCountFn = () =>{
|
|
||||||
getMyCouponStatusCount().then((res: any) =>{
|
|
||||||
statusList.value = res.data.filter((item: any) => item.status != 4)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const statusClickFn = (status: any) => {
|
|
||||||
couponStatus.value = status;
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getMyCouponListFn = (mescroll: any) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
status: couponStatus.value,
|
|
||||||
type: curType.value
|
|
||||||
};
|
|
||||||
|
|
||||||
getMyCouponList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const toLink = (coupon_id:any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/list',param:{coupon_id} })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 类型
|
|
||||||
const subActive = ref<number>(0)
|
|
||||||
const curType = ref('all')
|
|
||||||
const typeList = ref<Array<Object>>([])
|
|
||||||
const getMyCouponTypeFn = () =>{
|
|
||||||
getMyCouponType().then((res: any) =>{
|
|
||||||
const obj = { label: '全部', value: 'all' };
|
|
||||||
typeList.value.push(obj)
|
|
||||||
typeList.value = typeList.value.concat(res.data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onLoad(()=>{
|
|
||||||
getMyCouponTypeFn()
|
|
||||||
getMyCouponStatusCountFn()
|
|
||||||
})
|
|
||||||
|
|
||||||
const typeClick = (index : number,data:any) =>{
|
|
||||||
subActive.value = index
|
|
||||||
curType.value = data
|
|
||||||
list.value = []
|
|
||||||
getMescroll().resetUpScroll()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: 500 !important;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 10rpx;
|
|
||||||
height: 6rpx;
|
|
||||||
background-color: $u-primary;
|
|
||||||
width: 40rpx;
|
|
||||||
left: 50%;
|
|
||||||
border-radius: 100rpx;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.coupon-bg{
|
|
||||||
background: linear-gradient( 169deg, #FF7C36 0%, #FF2D00 86%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.coupon-item{
|
|
||||||
:before{
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 28rpx;
|
|
||||||
height: 28rpx;
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: -14rpx;
|
|
||||||
border-radius:14rpx;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
:after{
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 28rpx;
|
|
||||||
height: 28rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: -14rpx;
|
|
||||||
border-radius:14rpx;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(.mescroll-empty){
|
|
||||||
border-radius: var(--rounded-small) !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="min-h-[100vh] bg-[#f6f6f6] overflow-hidden" :style="themeColor()">
|
|
||||||
<block v-if="Object.keys(configInfo).length &&configInfo.active_status =='active'">
|
|
||||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getGoodsListFn">
|
|
||||||
<view class="marketing-head" v-if="!pageLoading">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<top-tabbar :data="param" :isFill="false" class="top-header"/>
|
|
||||||
<image v-if="configInfo.banner_list && configInfo.banner_list.length" class="w-[100%] h-[434rpx]" :src="img(configInfo.banner_list[0].imageUrl)" mode="aspectFill" @click="diyStore.toRedirect(configInfo.banner_list[0].toLink)"></image>
|
|
||||||
<!-- 占位作用 -->
|
|
||||||
<view v-else class="w-[100%] h-[434rpx]"></view>
|
|
||||||
<view v-if="configInfo.active_desc" class="side-tab" :style="{top: topStyle}" @click="newcomerPopup = true">
|
|
||||||
<text class="iconfont iconbiaoqianV6xx2 icon"></text>
|
|
||||||
<text class="desc">活动规则</text>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<image v-if="configInfo.banner_list && configInfo.banner_list.length" class="w-[100%] h-[434rpx] -mt-[130rpx]" :src="img(configInfo.banner_list[0].imageUrl)" mode="aspectFill" @click="diyStore.toRedirect(configInfo.banner_list[0].toLink)"></image>
|
|
||||||
<!-- 占位作用 -->
|
|
||||||
<view v-else class="w-[100%] h-[434rpx] -mt-[130rpx]"></view>
|
|
||||||
<view v-if="configInfo.active_desc" class="side-tab !top-[30rpx]" @click="newcomerPopup = true">
|
|
||||||
<text class="iconfont iconxinrenV6xx icon"></text>
|
|
||||||
<text class="desc">活动规则</text>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="time newcomer-time" v-if="newcomerTime > 0 && newcomerTime != undefined" :style="{'background-image': 'url('+ img('addon/shop/newcomer/time_bg.png') +')'}">
|
|
||||||
<text class="text-[26rpx]">距结束还有:</text>
|
|
||||||
<up-count-down class="text-[#fff] min-w-[150rpx] text-[28rpx]" :time="newcomerTime" format="DD:HH:mm:ss" @change="onChange">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="text-[24rpx] flex items-center" v-if="timeData.days && timeData.days>0">
|
|
||||||
<text class="min-w-[30rpx] text-right">{{ timeData.days }}</text>
|
|
||||||
<text class="text-[20rpx]">天</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="min-w-[30rpx] text-center" v-if="timeData.hours">{{ timeData.hours>=10?timeData.hours:'0'+timeData.hours}}</text>
|
|
||||||
<text class="min-w-[30rpx] text-center" v-else>00</text>
|
|
||||||
<text class="text-[20rpx]">时</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="min-w-[30rpx] text-center" v-if="timeData.minutes">{{ timeData.minutes >= 10 ? timeData.minutes :'0'+timeData.minutes }}</text>
|
|
||||||
<text class="min-w-[30rpx] text-center" v-else>00</text>
|
|
||||||
<text class="text-[20rpx]">分</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] flex items-center">
|
|
||||||
<text class="min-w-[30rpx] text-center" v-if="timeData.seconds">{{ timeData.seconds<10 ? '0'+timeData.seconds : timeData.seconds}}</text>
|
|
||||||
<text class="min-w-[30rpx] text-center" v-else>00</text>
|
|
||||||
<text class="text-[20rpx]">秒</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-count-down>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="marketing-list p-[20rpx] relative -mt-[50rpx]" v-if="goodsList.length">
|
|
||||||
<view class="bg-[#fff] flex rounded-[var(--rounded-mid)] p-[20rpx]" v-for="(item,index) in goodsList" :key="index" :class="{'mb-[20rpx]': (goodsList.length-1) != index}" @click="toDetail(item)">
|
|
||||||
<view class="w-[250rpx] h-[250rpx] flex items-center justify-center">
|
|
||||||
<image v-if="item.goods_cover" class="w-[250rpx] h-[250rpx] rounded-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[250rpx] h-[250rpx] rounded-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col flex-1 ml-[20rpx] pt-[4rpx]">
|
|
||||||
<view class="text-[28rpx] multi-hidden leading-[1.3]">{{item.goods_name}}</view>
|
|
||||||
<view class="w-[400rpx] flex items-center justify-center">
|
|
||||||
<image class="w-[400rpx] h-[106rpx] mt-[auto] mb-[10rpx]" :src="img('addon/shop/newcomer/subsidy.png')" mode="aspectFit"></image>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-center btn-wrap">
|
|
||||||
<view class="flex items-center text-[#FFF3E0] relative z-4" :style="{'background': 'linear-gradient(to right, #FF8A04 0%, #ff1b1b 84%)'}">
|
|
||||||
<text class="text-[22rpx]">新人价</text>
|
|
||||||
<text class="text-[20rpx] ml-[6rpx] mr-[2rpx]">¥</text>
|
|
||||||
<text class="text-[36rpx] truncate max-w-[160rpx]">{{parseFloat(item.goodsSku.newcomer_price).toFixed(2)}}</text>
|
|
||||||
</view>
|
|
||||||
<image class="w-[26rpx] h-[54rpx]" :src="img('addon/shop/newcomer/btn_02.png')" mode="heightFix"></image>
|
|
||||||
<image class="w-[84rpx] h-[54rpx] relative ml-[-5rpx] z-2" :src="img('addon/shop/newcomer/btn_03.png')" mode="aspectFit"></image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-else-if="!goodsList.length && loading" :option="{tip : '暂无商品,请看看其他商品吧!', btnText:'去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/goods/list' })"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
</block>
|
|
||||||
<block v-if="!pageLoading && Object.keys(configInfo).length && configInfo.active_status !='active'">
|
|
||||||
<top-tabbar :data="pageNullParam" class="top-header"/>
|
|
||||||
<mescroll-empty :option="{tip : '活动未开启,请看看其他商品吧!', btnText:'去逛逛'}" @emptyclick="redirect({ url: '/addon/shop/pages/index' })"></mescroll-empty>
|
|
||||||
</block>
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup :show="newcomerPopup" @close="closeFn" mode="center" round="var(--rounded-big)">
|
|
||||||
<view class="w-[570rpx] px-[32rpx] popup-common center">
|
|
||||||
<view class="title">活动规则</view>
|
|
||||||
<scroll-view :scroll-y="true" class="px-[30rpx] box-border max-h-[260rpx]" v-if="configInfo.active_desc">
|
|
||||||
<block v-for="(item) in configInfo.active_desc.split('\n')">
|
|
||||||
<view class="text-[28rpx] leading-[40rpx] mb-[20rpx]">{{ item }}</view>
|
|
||||||
</block>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap !pt-[40rpx]">
|
|
||||||
<button class="primary-btn-bg w-[480rpx] h-[70rpx] text-[26rpx] leading-[70rpx] rounded-[35rpx] !text-[#fff] font-500" @click="newcomerPopup = false">我知道了</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
<loading-page :loading="pageLoading"></loading-page>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, computed } from 'vue'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect, img, getToken, pxToRpx, timeTurnTimeStamp } from '@/utils/common';
|
|
||||||
import { getNewcomerGoodsList, getNewcomersConfig } from '@/addon/shop/api/newcomer';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
|
||||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import useDiyStore from '@/app/stores/diy';
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
const mescrollRef = ref(null);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const pageLoading = ref<boolean>(true);
|
|
||||||
const diyStore = useDiyStore();
|
|
||||||
// 获取系统状态栏的高度
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let param = topTabarObj.setTopTabbarParam({title:'',topStatusBar: {textColor: '#fff'}})
|
|
||||||
let pageNullParam = topTabarObj.setTopTabbarParam({title:'新人专享列表',topStatusBar: {textColor: '#333'} })
|
|
||||||
const topStyle = computed(() => {
|
|
||||||
let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 30 + 'rpx;'
|
|
||||||
return style
|
|
||||||
})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
|
|
||||||
/********* 倒计时 - start ***********/
|
|
||||||
// 使用 reactive 创建响应式对象
|
|
||||||
const timeData = ref({});
|
|
||||||
// 定义 onChange 方法
|
|
||||||
const onChange = (e) => {
|
|
||||||
timeData.value = e;
|
|
||||||
};
|
|
||||||
const newcomerTime = ref('');
|
|
||||||
/********* 倒计时 - end ***********/
|
|
||||||
|
|
||||||
/**************** 活动规则 ********************/
|
|
||||||
const newcomerPopup = ref(false)
|
|
||||||
const closeFn = () =>{
|
|
||||||
newcomerPopup.value = false
|
|
||||||
}
|
|
||||||
/**************** 活动规则 - end ********************/
|
|
||||||
onLoad(async (option: any) => {
|
|
||||||
getNewcomersConfigFn();
|
|
||||||
})
|
|
||||||
|
|
||||||
const configInfo = ref({});
|
|
||||||
const getNewcomersConfigFn = () => {
|
|
||||||
getNewcomersConfig().then((res: any) => {
|
|
||||||
configInfo.value = res.data;
|
|
||||||
let time = configInfo.value && configInfo.value.validity_time ? timeTurnTimeStamp(configInfo.value.validity_time) : 0;
|
|
||||||
pageLoading.value = false;
|
|
||||||
}).catch(()=>{
|
|
||||||
pageLoading.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const isJoin = ref(0) // 是否参与过新人专享活动,1:是,0:否
|
|
||||||
const getGoodsListFn = (mescroll: mescrollStructure) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size
|
|
||||||
};
|
|
||||||
getNewcomerGoodsList(data).then((res: any) => {
|
|
||||||
isJoin.value = res.data.is_join;
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
let now = new Date();
|
|
||||||
let timestamp: any = now.getTime();
|
|
||||||
newcomerTime.value = Number(res.data.validity_time) * 1000 - timestamp;
|
|
||||||
//设置列表数据
|
|
||||||
if (Number(mescroll.num) === 1) {
|
|
||||||
goodsList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
goodsList.value = goodsList.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toDetail = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/goods/detail', param: { sku_id: data.goodsSku.sku_id, type: 'newcomer_discount' } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.marketing-head{
|
|
||||||
position: relative;
|
|
||||||
.time{
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 44rpx;
|
|
||||||
line-height: 1;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #fff;
|
|
||||||
width: 660rpx;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
bottom: 84rpx;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.marketing-list{
|
|
||||||
// background: linear-gradient(180deg, rgba(255,240,242, 1), rgba(255,255,255, 0) 35%);
|
|
||||||
background: linear-gradient( 180deg, #FFF2F0 23%, #F6F6F6 92%);
|
|
||||||
border-radius: 34rpx 34rpx 0 0;
|
|
||||||
.btn-wrap{
|
|
||||||
border-radius: 50rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
align-self: center;
|
|
||||||
position: relative;
|
|
||||||
view{
|
|
||||||
height: 54rpx;
|
|
||||||
padding-left: 16rpx;
|
|
||||||
padding-right: 30rpx;
|
|
||||||
}
|
|
||||||
image:nth-of-type(1){
|
|
||||||
position: absolute;
|
|
||||||
right: 54rpx;
|
|
||||||
top: 0rpx;
|
|
||||||
height: 54rpx;
|
|
||||||
z-index: 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #ifdef MP */
|
|
||||||
.newcomer-time{
|
|
||||||
animation: fadein .15s;
|
|
||||||
}
|
|
||||||
/* 进入动画 */
|
|
||||||
@keyframes fadein {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
99% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
</style>
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<template>
|
|
||||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10">
|
|
||||||
<view @touchmove.prevent.stop class="popup-common">
|
|
||||||
<view class="title">{{t('selectAddress')}}</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[50vh]">
|
|
||||||
<view v-for="(item,index) in addressList" :key="item.id" class="flex items-center mx-[var(--popup-sidebar-m)] border-1 border-[#eee] border-solid rounded-[var(--rounded-mid)] px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)]" :class="{'mb-[var(--top-m)]': addressList.length-1 != index, 'text-[var(--primary-color)] !border-[var(--primary-color)]': item.id == currAddressId}" @click="selectAddress(index)">
|
|
||||||
<text class="nc-iconfont nc-icon-dingweiV6xx-1 text-[36rpx]"></text>
|
|
||||||
<view class="flex flex-col mx-[20rpx] w-[480rpx]">
|
|
||||||
<view class="flex items-center truncate leading-[1.5]">
|
|
||||||
<text class="mr-[8rpx] text-[30rpx] truncate max-w-[300rpx]">{{item.name}}</text>
|
|
||||||
<text class="text-[30rpx]">{{item.mobile}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="truncate text-[26rpx] leading-[1.5] mt-[12rpx]">{{item.full_address}}</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-xiugaiV6xx text-[32rpx] ml-auto" @click="editAddress(item)"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="!addressList || addressList && !addressList.length" class="text-[var(--text-color-light6)] text-[28rpx] text-center">{{t('emptyAddress')}}</view>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="addAddress">{{t('addAddress')}}</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { getAddressList } from '@/app/api/member'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect } from '@/utils/common'
|
|
||||||
|
|
||||||
const show = ref(false)
|
|
||||||
const loading = ref(false)
|
|
||||||
const currAddressId = ref('') // 选中的索引
|
|
||||||
const propData: any = ref({})
|
|
||||||
const addressList: any = ref([])
|
|
||||||
|
|
||||||
const emits = defineEmits(['confirm'])
|
|
||||||
|
|
||||||
const open = (data: any) => {
|
|
||||||
show.value = true;
|
|
||||||
propData.value = data;
|
|
||||||
currAddressId.value = data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
getAddressList({}).then(({ data }) => {
|
|
||||||
addressList.value = data;
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectAddress = (index: number) => {
|
|
||||||
let data = addressList.value[index];
|
|
||||||
if(propData.value.delivery == 'local_delivery' && !data.lat && !data.lng){
|
|
||||||
// 待支付订单-同城配送,选择的地址没有经纬度的情况,会直接跳转到地图界面进行选择
|
|
||||||
// 参数二,表示是否直接跳转到地图界面, 1跳转到地图界面,2表示不跳
|
|
||||||
editAddress(data,1);
|
|
||||||
}else{
|
|
||||||
let obj:any = {}
|
|
||||||
obj.address_id = addressList.value[index].id
|
|
||||||
obj.delivery = propData.value.delivery
|
|
||||||
emits('confirm', obj)
|
|
||||||
}
|
|
||||||
show.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const editAddress = (data: any, isSelectMap: number = 2)=>{
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'selectAddressCallback',
|
|
||||||
data: {
|
|
||||||
back: '/addon/shop/pages/order/payment',
|
|
||||||
delivery: propData.value.delivery
|
|
||||||
},
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/app/pages/member/address_edit', param: { id: data.id, source: 'shop_order_payment', isSelectMap } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const addAddress = () =>{
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'selectAddressCallback',
|
|
||||||
data: {
|
|
||||||
back: '/addon/shop/pages/order/payment',
|
|
||||||
delivery: propData.value.delivery
|
|
||||||
},
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/app/pages/member/address_edit', param: { source: 'shop_order_payment' } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
<template>
|
|
||||||
<u-popup :show="invoicePop" @close="closeFn" mode="bottom" >
|
|
||||||
<!-- class="bg-[#fff] rounded-[10rpx] popup-common" @touchmove.prevent.stop -->
|
|
||||||
<view class="popup-common">
|
|
||||||
<view class="title">请填写发票信息</view>
|
|
||||||
<scroll-view :scroll-y="true" class="h-[50vh]">
|
|
||||||
<view class="px-[var(--popup-sidebar-m)] pb-[60rpx] pt-0 text-sm ">
|
|
||||||
<u-form labelPosition="left" :model="formData" labelWidth="200rpx" :labelStyle="{'font-size': '28rpx'}" errorType='toast' :rules="rules" ref="formRef">
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="需要发票" leftIconStyle="text-[28rpx]">
|
|
||||||
<view class="flex">
|
|
||||||
<view
|
|
||||||
class="h-[60rpx] box-border rounded px-[30rpx] leading-[56rpx] mr-[20rpx] border-[2rpx] border-[var(--temp-bg)] bg-[var(--temp-bg)] border-solid text-[24rpx]"
|
|
||||||
:class="{'!bg-[var(--primary-color-light)] !text-[var(--primary-color)] !border-primary': !need}"
|
|
||||||
@click="need = false">不需要</view>
|
|
||||||
<view class="h-[60rpx] box-border rounded px-[30rpx] leading-[56rpx] border-[2rpx] border-[var(--temp-bg)] border-solid text-[24rpx] bg-[var(--temp-bg)]"
|
|
||||||
:class="{'!bg-[var(--primary-color-light)] !text-[var(--primary-color)] !border-primary': need}"
|
|
||||||
@click="need = true">需要</view>
|
|
||||||
</view>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view v-show="need">
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="抬头类型">
|
|
||||||
<view class="flex">
|
|
||||||
<view
|
|
||||||
class="h-[60rpx] box-border rounded px-[30rpx] mr-[20rpx] leading-[56rpx] border-[2rpx] border-[var(--temp-bg)] border-solid text-[24rpx] bg-[var(--temp-bg)]"
|
|
||||||
:class="{'!bg-[var(--primary-color-light)] !text-[var(--primary-color)] !border-primary': formData.header_type == 1}"
|
|
||||||
@click="formData.header_type = 1">个人</view>
|
|
||||||
<view class="h-[60rpx] box-border rounded px-[30rpx] leading-[56rpx] border-[2rpx] border-[var(--temp-bg)] border-solid text-[24rpx] bg-[var(--temp-bg)]"
|
|
||||||
:class="{'!bg-[var(--primary-color-light)] !text-[var(--primary-color)] !border-primary': formData.header_type == 2}"
|
|
||||||
@click="formData.header_type = 2">企业</view>
|
|
||||||
</view>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="发票内容" prop="header_name">
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<block v-for="(item,index) in config.invoice_content">
|
|
||||||
<view class="box-border rounded px-[20rpx] py-[12rpx] leading-[1.4] border-[2rpx] border-[var(--temp-bg)] border-solid text-[24rpx] bg-[var(--temp-bg)] my-[10rpx]"
|
|
||||||
:class="{'!bg-[var(--primary-color-light)] !text-[var(--primary-color)] !border-primary': formData.name == item, 'mr-[20rpx]': (config.invoice_content.length-1) != index}"
|
|
||||||
@click="formData.name = item">{{ item }}</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="发票抬头" prop="header_name">
|
|
||||||
<u-input fontSize="28rpx" v-model.trim="formData.header_name" border="none" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" clearable placeholder="请输入发票抬头" ></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view v-if="formData.header_type == 2">
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="纳税人识别号" prop="tax_number">
|
|
||||||
<u-input fontSize="28rpx" v-model.trim="formData.tax_number" border="none" clearable placeholder="请输入纳税人识别号" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" @change="inputChange"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<!-- <view class="py-[20rpx] h-[48rpx] flex items-center">
|
|
||||||
<text class="text-[30rpx]">更多选填内容</text>
|
|
||||||
<text class="text-xs text-gray-subtitle ml-[10rpx]">注册地址、电话、开户银行及账号</text>
|
|
||||||
<view class="text-xs text-right flex-1" @click="optionalShow = !optionalShow">
|
|
||||||
<text>{{ optionalShow ? '收起' : '展开' }}</text>
|
|
||||||
<text class="text-[30rpx] nc-iconfont text-gray-subtitle ml-[5rpx]" :class="optionalShow ? 'nc-icon-shangV6xx-1' : 'nc-icon-xiaV6xx'"></text>
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="注册地址">
|
|
||||||
<u-input fontSize="28rpx" v-model="formData.address" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" border="none" clearable placeholder="(选填)请输入企业注册地址"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="注册电话">
|
|
||||||
<u-input fontSize="28rpx" v-model="formData.telephone" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" border="none" clearable placeholder="(选填)请输入企业注册电话"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="开户银行">
|
|
||||||
<u-input fontSize="28rpx" v-model="formData.bank_name" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" border="none" clearable placeholder="(选填)请输入企业开户银行"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[10rpx]">
|
|
||||||
<u-form-item label="银行账号">
|
|
||||||
<u-input fontSize="28rpx" v-model="formData.bank_card_number" placeholder-class="!text-[var(--text-color-light9)] text-[28rpx]" border="none" clearable placeholder="(选填)请输入企业开户银行账号"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-form>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="confirm">确认</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed,nextTick } from 'vue'
|
|
||||||
import { getInvoiceConfig } from '@/addon/shop/api/config'
|
|
||||||
|
|
||||||
const invoicePop = ref(false)
|
|
||||||
const config = ref({
|
|
||||||
is_invoice: 2,
|
|
||||||
invoice_content: []
|
|
||||||
})
|
|
||||||
const need = ref(false)
|
|
||||||
const optionalShow = ref(false)
|
|
||||||
const formData: any = ref({
|
|
||||||
header_type: 1,
|
|
||||||
header_name: '',
|
|
||||||
type: '',
|
|
||||||
name: '',
|
|
||||||
tax_number: '',
|
|
||||||
telephone: '',
|
|
||||||
address: '',
|
|
||||||
bank_name: '',
|
|
||||||
bank_card_number: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
const invoiceOpen = computed(() => {
|
|
||||||
return config.value.is_invoice == 1
|
|
||||||
})
|
|
||||||
|
|
||||||
getInvoiceConfig().then(({ data }) => {
|
|
||||||
config.value = data
|
|
||||||
data.invoice_content.length && (formData.value.name = data.invoice_content[0])
|
|
||||||
}).catch()
|
|
||||||
|
|
||||||
const inputChange = (e: any) =>{
|
|
||||||
nextTick(()=>{
|
|
||||||
formData.value.tax_number = e.replace(/[^0-9a-zA-Z]/g,'')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const formRef: any = ref(null)
|
|
||||||
|
|
||||||
const rules = computed(() => {
|
|
||||||
return {
|
|
||||||
'header_name': {
|
|
||||||
type: 'string',
|
|
||||||
required: need.value,
|
|
||||||
message: '请输入发票抬头',
|
|
||||||
trigger: ['blur', 'change'],
|
|
||||||
},
|
|
||||||
'tax_number': [{
|
|
||||||
type: 'string',
|
|
||||||
required: need.value && formData.value.header_type == 2,
|
|
||||||
message: '请输入纳税人识别号',
|
|
||||||
trigger: ['blur', 'change'],
|
|
||||||
}, {
|
|
||||||
validator(rule: any, value: any, callback: any) {
|
|
||||||
const limit = /^[0-9a-zA-Z]+$/;
|
|
||||||
if (!limit.test(value) && formData.header_type == 2) {
|
|
||||||
callback(new Error('请输入正确的纳税人识别号'))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const open = () => {
|
|
||||||
invoicePop.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emits = defineEmits(['confirm'])
|
|
||||||
|
|
||||||
const confirm = () => {
|
|
||||||
formRef.value.validate().then(() => {
|
|
||||||
const invoice = need.value ? formData.value : {}
|
|
||||||
emits('confirm', invoice)
|
|
||||||
invoicePop.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const closeFn = () =>{
|
|
||||||
invoicePop.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
invoiceOpen
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup :show="showpop" mode="bottom" :round="10" @close="close" :closeable="true" :safeAreaInsetBottom="true" @touchmove.prevent.stop>
|
|
||||||
<view class="h-[70vh] px-[24rpx] bg-page pb-[20rpx]" @touchmove.prevent.stop v-if="Object.keys(showList).length">
|
|
||||||
<view class="font-500 text-center text-[32rpx] leading-[104rpx] box-border h-[104rpx]">{{t('detailedInformation')}}</view>
|
|
||||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="'id' + (subActive>3 ? subActive - 2 : 0)" >
|
|
||||||
<view class="flex py-[22rpx] whitespace-nowrap" v-if="packageList.length > 1">
|
|
||||||
<view :id="'id' + index" class="text-[26rpx] leading-[36rpx] mr-[30rpx] text-[#626779]" :class="{'!text-primary class-select': item.id == current}" v-for="(item,index) in packageList" :key="index" @click="handleClick(item,index)">{{ item.name }}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="text-[28rpx] mt-[20rpx] ">
|
|
||||||
<view class="flex justify-between mb-[20rpx]">
|
|
||||||
<template v-if="showList.sub_delivery_type == 'none_express'">
|
|
||||||
<text class="mr-[20rpx]">无需物流</text>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<text class="mr-[20rpx]">{{showList.company.company_name}}</text>
|
|
||||||
<view>
|
|
||||||
<text class="mr-[14rpx]">{{showList.express_number}}</text>
|
|
||||||
<text @click="copy(showList.express_number)">{{t('copy')}}</text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="parcel" style="height: 53vh;" v-if="showList.sub_delivery_type == 'express'">
|
|
||||||
<view class="h-[56vh] flex flex-col items-center justify-center" v-if="showList.traces.success == false">
|
|
||||||
<text class="nc-iconfont nc-icon-daishouhuoV6xx text-[180rpx] text-[#bfbfbf]"></text>
|
|
||||||
<view class="text-[28rpx] text-[#bfbfbf] leading-8">暂无物流信息~~</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view v-else :scroll-y="true" style="height:53vh;padding: 20rpx;box-sizing: border-box;" class="bg-white rounded-md">
|
|
||||||
<u-steps :current="0" dot direction="column" activeColor="var(--primary-color)">
|
|
||||||
<block v-for="(item,index) in showList.traces.list" :key="index + 'id'">
|
|
||||||
<u-steps-item :title="item.remark" :desc="item.datetime"></u-steps-item>
|
|
||||||
</block>
|
|
||||||
</u-steps>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<view style="height: 53vh;" v-else-if="showList.sub_delivery_type == 'none_express'">
|
|
||||||
<view class="h-[56vh] flex-col flex items-center justify-center">
|
|
||||||
<text class="nc-iconfont nc-icon-daishouhuoV6xx text-[180rpx] text-[#bfbfbf]"></text>
|
|
||||||
<view class="text-[28rpx] text-[#bfbfbf] leading-8">无需物流~~</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import {ref} from 'vue'
|
|
||||||
import {t} from '@/locale'
|
|
||||||
import {img, redirect, copy} from '@/utils/common';
|
|
||||||
import {getMaterialflowList} from '@/addon/shop/api/order';
|
|
||||||
|
|
||||||
const showpop = ref(false)
|
|
||||||
const packageList = ref([])
|
|
||||||
const showList = ref<any>({})
|
|
||||||
const loadList = async (params: any) => {
|
|
||||||
let data: any = await getMaterialflowList(params)
|
|
||||||
showList.value = data.data
|
|
||||||
}
|
|
||||||
const current = ref(0)
|
|
||||||
const subActive = ref(0)
|
|
||||||
|
|
||||||
const open = (params: any) => {
|
|
||||||
current.value= params.id
|
|
||||||
loadList(params)
|
|
||||||
showpop.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const close = () => {
|
|
||||||
showpop.value = false
|
|
||||||
}
|
|
||||||
const handleClick = (item: any,index:number) => {
|
|
||||||
current.value = item.id
|
|
||||||
subActive.value = index
|
|
||||||
let params = {
|
|
||||||
id: item.id,
|
|
||||||
mobile: item.mobile
|
|
||||||
}
|
|
||||||
loadList(params)
|
|
||||||
}
|
|
||||||
defineExpose({
|
|
||||||
packageList,
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.parcel :deep(.u-text__value) {
|
|
||||||
font-size: 24rpx !important;
|
|
||||||
line-height: 42rpx !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parcel :deep(.u-steps-item__content) {
|
|
||||||
margin-left: 20rpx !important;
|
|
||||||
}
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: -6rpx;
|
|
||||||
height: 4rpx;
|
|
||||||
background-color: $u-primary;
|
|
||||||
width: 26rpx;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
<template>
|
|
||||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10" :closeable="true">
|
|
||||||
<view @touchmove.prevent.stop class="popup-common">
|
|
||||||
<view class="title">请选择优惠券</view>
|
|
||||||
<view v-if="!type" class="-mt-[20rpx]">
|
|
||||||
<u-tabs :list="tabs" @click="switchTab" :current="current" itemStyle="width:50%;height:88rpx;box-sizing: border-box; font-size: 28rpx;"
|
|
||||||
:activeStyle="{
|
|
||||||
color: 'var(--primary-color)'
|
|
||||||
}" lineColor="var(--primary-color)"></u-tabs>
|
|
||||||
</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[50vh] pt-[10rpx]">
|
|
||||||
<view class="px-[var(--popup-sidebar-m)] pb-[30rpx] pt-0 text-sm" v-show="current == 0">
|
|
||||||
<view class="mt-[var(--top-m)] px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)] border-1 border-[#eee] border-solid rounded-[20rpx]"
|
|
||||||
:class="{'!border-[var(--primary-color)] bg-[var(--primary-color-light2)]': coupon && coupon.id == item.id}"
|
|
||||||
v-for="item in couponList"
|
|
||||||
@click="selectCoupon(item)">
|
|
||||||
<view class="flex border-0 !border-b border-[#eee] border-dashed pb-[20rpx]" :class="{ '!border-[var(--primary-color)]': coupon && coupon.id == item.id }">
|
|
||||||
<view class="flex-1 w-0">
|
|
||||||
<view class="text-[30rpx] mb-[20rpx] font-500">{{ item.title }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)]" v-if="item.min_condition_money > 0">满{{ item.min_condition_money }}可用</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)]" v-else>无门槛券</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[36rpx] price-font"><text class="text-xs mr-[2rpx]">¥</text>{{ item.price }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="pt-[20rpx] text-[24rpx] text-[var(--text-color-light6)]">{{ item.create_time }} ~ {{ item.expire_time }}有效</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="px-[var(--popup-sidebar-m)] pb-[30rpx] pt-0 text-sm" v-show="current == 1">
|
|
||||||
<view class="mt-[var(--top-m)] px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)] border-1 !border-[#eee] border-solid rounded-[var(--rounded-mid)] bg-[var(--temp-bg)]" v-for="item in disabledCouponList">
|
|
||||||
<view class="flex border-0 !border-b !border-[#ddd] border-dashed pb-[20rpx]">
|
|
||||||
<view class="flex-1 w-0">
|
|
||||||
<view class="text-[30rpx] mb-[20rpx] font-500">{{ item.title }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light9)]" v-if="item.min_condition_money > 0">满{{ item.min_condition_money }}可用</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light9)]" v-else>无门槛券</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[36rpx] price-font"><text class="text-xs mr-[2rpx]">¥</text>{{ item.price }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="pt-[20rpx] text-[24rpx] text-[var(--text-color-light9)]">{{ item.create_time }} ~ {{ item.expire_time }}期间有效</view>
|
|
||||||
<view class="text-[24rpx] pt-[10rpx] flex text-[var(--text-color-light9)]">
|
|
||||||
不可用原因:{{ item.error }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="confirm">确认</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, watch, computed } from 'vue'
|
|
||||||
import { orderCoupon } from '@/addon/shop/api/order'
|
|
||||||
|
|
||||||
const prop = defineProps({
|
|
||||||
orderKey: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const current = ref(0)
|
|
||||||
const couponList = ref<object[]>([])
|
|
||||||
const disabledCouponList = ref<object[]>([])
|
|
||||||
const show = ref(false)
|
|
||||||
const coupon = ref<null | object>(null)
|
|
||||||
const emits = defineEmits(['confirm'])
|
|
||||||
|
|
||||||
watch(() => prop.orderKey, () => {
|
|
||||||
if (prop.orderKey && !couponList.value.length) {
|
|
||||||
orderCoupon({order_key: prop.orderKey}).then(({data}) => {
|
|
||||||
const list = [], disabled = []
|
|
||||||
|
|
||||||
if (data.length) {
|
|
||||||
data.forEach(item => {
|
|
||||||
item.is_normal ? list.push(item) : disabled.push(item)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
disabledCouponList.value = disabled
|
|
||||||
couponList.value = list
|
|
||||||
|
|
||||||
if (list.length) {
|
|
||||||
coupon.value = list[0]
|
|
||||||
emits('confirm', coupon.value)
|
|
||||||
}
|
|
||||||
}).catch()
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
const tabs = computed(() => {
|
|
||||||
return [
|
|
||||||
{ name: `可用优惠券(${couponList.value.length})`, key: 'normal' },
|
|
||||||
{ name: `不可用优惠券(${disabledCouponList.value.length})`, key: 'disabled' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
const switchTab = (event: any)=> {
|
|
||||||
current.value = event.index
|
|
||||||
}
|
|
||||||
|
|
||||||
const open = (coupon_id:any)=> {
|
|
||||||
show.value = true
|
|
||||||
if(coupon_id){
|
|
||||||
for(let i=0;i<couponList.value.length;i++){
|
|
||||||
if(couponList.value[i].id == coupon_id){
|
|
||||||
coupon.value = couponList.value[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectCoupon = (data: object)=> {
|
|
||||||
if (coupon.value) {
|
|
||||||
coupon.value = coupon.value.id != data.id ? data : null
|
|
||||||
} else {
|
|
||||||
coupon.value = data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirm = ()=> {
|
|
||||||
emits('confirm', coupon.value)
|
|
||||||
show.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
couponList
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
<template>
|
|
||||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10">
|
|
||||||
<view @touchmove.prevent.stop class="popup-common">
|
|
||||||
<view class="title">请选择自提点</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[50vh]">
|
|
||||||
<view class="p-[var(--popup-sidebar-m)] pt-0 text-sm">
|
|
||||||
<view class="mt-[var(--top-m)] border-1 border-[#eee] border-solid rounded-[var(--rounded-mid)] px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)] mb-[var(--top-m)]" :class="{'!border-primary bg-[var(--primary-color-light2)]': store && store.store_id == item.store_id}" v-for="item in storeList" @click="selectStore(item)">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="flex-1 w-0">
|
|
||||||
<text class="text-[30rpx] text-[#333]">{{ item.store_name }}</text>
|
|
||||||
<text class="text-[26rpx] ml-[12rpx] text-[var(--text-color-light6)]">{{ item.store_mobile }}</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.distance">
|
|
||||||
<text class="text-red text-[26rpx] font-normal">{{ distanceFormat(item.distance) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] text-[26rpx] leading-[1.4] flex">
|
|
||||||
<text class="flex-shrink-0">门店地址:</text>
|
|
||||||
<text>{{ item.full_address }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[16rpx] text-[26rpx]">营业时间:{{ item.trade_time }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="h-[50vh] flex items-center flex-col justify-center" v-if="loading">
|
|
||||||
<u-loading-icon :vertical="true"></u-loading-icon>
|
|
||||||
</view>
|
|
||||||
<view class="h-[95%] flex items-center flex-col justify-center" v-if="!loading && !storeList.length">
|
|
||||||
<u-empty text="没有可选择的自提点" width="214" :icon="img('static/resource/images/empty.png')"/>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="confirm">确认</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref,reactive } from 'vue'
|
|
||||||
import { getStoreList } from '@/addon/shop/api/order'
|
|
||||||
import { img } from '@/utils/common'
|
|
||||||
|
|
||||||
const show = ref(false)
|
|
||||||
const loaded = ref(false)
|
|
||||||
const loading = ref(true)
|
|
||||||
const storeList = ref<object[]>([])
|
|
||||||
const store = ref<null | object>(null)
|
|
||||||
|
|
||||||
const latlng = reactive({
|
|
||||||
lat:0,
|
|
||||||
lng:0
|
|
||||||
})
|
|
||||||
|
|
||||||
const getStoreListFn = (callback:any)=>{
|
|
||||||
if (!loaded.value) {
|
|
||||||
loaded.value = true
|
|
||||||
|
|
||||||
if(uni.getStorageSync('location_address')){
|
|
||||||
let location_address = uni.getStorageSync('location_address');
|
|
||||||
latlng.lat = location_address.latitude;
|
|
||||||
latlng.lng = location_address.longitude;
|
|
||||||
}else{
|
|
||||||
uni.getLocation({
|
|
||||||
type: 'gcj02',
|
|
||||||
success: (res) => {
|
|
||||||
latlng.lat = res.latitude
|
|
||||||
latlng.lng = res.longitude
|
|
||||||
},
|
|
||||||
fail: (res) => {
|
|
||||||
if (res.errno) {
|
|
||||||
if (res.errno == 104) {
|
|
||||||
let msg = '用户未授权隐私权限,获取位置失败';
|
|
||||||
uni.showToast({ title: msg, icon: 'none' })
|
|
||||||
} else if (res.errno == 112) {
|
|
||||||
let msg = '隐私协议中未声明,获取位置失败';
|
|
||||||
uni.showToast({ title: msg, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res.errMsg) {
|
|
||||||
if (res.errMsg.indexOf('getLocation:fail') != -1 || res.errMsg.indexOf('deny') != -1 || res.errMsg.indexOf('denied') != -1) {
|
|
||||||
let msg = '用户未授权获取位置权限,将无法提供距离最近的门店';
|
|
||||||
uni.showToast({ title: msg, icon: 'none' })
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: res.errMsg, icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
getStoreList({ latlng }).then(({ data }) => {
|
|
||||||
storeList.value = data
|
|
||||||
if(typeof callback == 'function'){
|
|
||||||
callback(data);
|
|
||||||
}
|
|
||||||
loading.value = false
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
}, 1500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const open = ()=> {
|
|
||||||
show.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectStore = (data: object)=> {
|
|
||||||
if (store.value) {
|
|
||||||
store.value = store.value.store_id != data.store_id ? data : null
|
|
||||||
} else {
|
|
||||||
store.value = data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const emits = defineEmits(['confirm'])
|
|
||||||
|
|
||||||
const confirm = ()=> {
|
|
||||||
emits('confirm', store.value)
|
|
||||||
show.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const distanceFormat = (distance: any) => {
|
|
||||||
distance = parseFloat(distance)
|
|
||||||
if (distance < 1000) {
|
|
||||||
return `${distance}m`;
|
|
||||||
} else {
|
|
||||||
const km = (distance / 1000).toFixed(2)
|
|
||||||
return `${km}km`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
getData: getStoreListFn
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
@@ -1,726 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="!loading">
|
|
||||||
<view v-if="!loading" class="pb-20rpx">
|
|
||||||
<view v-if="detail.status_name" class="pl-[40rpx] pr-[50rpx] bg-linear pb-[100rpx]">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="flex justify-between items-center pt-[40rpx]">
|
|
||||||
<view class="text-[#fff] text-[36rpx] font-500 leading-[42rpx]">{{ detail.status_name.name }}</view>
|
|
||||||
<image v-if="detail.status == 1" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/payment.png')" mode="aspectFit" />
|
|
||||||
<image v-if="detail.status == 2" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/deliver_goods.png')" mode="aspectFit" />
|
|
||||||
<image v-if="detail.status == 3" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/receive.png')" mode="aspectFit" />
|
|
||||||
<image v-if="detail.status == 5" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/complete.png')" mode="aspectFit" />
|
|
||||||
<image v-if="detail.status == -1" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/close.png')" mode="aspectFit" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin mt-[-86rpx] card-template" v-if="detail.delivery_type != 'virtual'">
|
|
||||||
<view v-if="detail.delivery_type == 'express'">
|
|
||||||
<view class="text-[#303133] flex">
|
|
||||||
<text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[40rpx] pt-[12rpx] mr-[20rpx]"></text>
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[30rpx] leading-[38rpx] overflow-hidden">
|
|
||||||
<text>{{ detail.taker_name }}</text>
|
|
||||||
<text class="ml-[15rpx]">{{ detail.taker_mobile }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[12rpx] text-[24rpx] text-[var(--text-color-light6)] leading-[26rpx]">
|
|
||||||
{{detail.taker_full_address.split(detail.taker_address)[0]}}{{detail.taker_address}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="detail.delivery_type == 'store'">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view>
|
|
||||||
<u--image class="overflow-hidden" radius="var(--goods-rounded-mid)" width="100rpx" height="100rpx"
|
|
||||||
:src="img(detail.store.store_logo ? detail.store.store_logo : '')"
|
|
||||||
model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[100rpx] h-[100rpx] rounded-[var(--goods-rounded-mid)] overflow-hidden" :src="img('addon/shop/store_default.png')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col ml-[20rpx]">
|
|
||||||
<text class="text-[30rpx] font-500 text-[#303133] mb-[20rpx]">{{ detail.store.store_name }}</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light6)] mb-[14rpx]">{{ detail.store.trade_time }}</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light6)] leading-[1.4]">{{ detail.store.full_address }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex" v-if="detail.delivery_type == 'local_delivery'">
|
|
||||||
<text @click="getAddress" class="nc-iconfont nc-icon-dizhiguanliV6xx text-[40rpx] pt-[12rpx] mr-[20rpx]"></text>
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="flex leading-[38rpx] overflow-hidden">
|
|
||||||
<text class="text-[30rpx]">{{ detail.taker_name }}</text>
|
|
||||||
<text class="text-[30rpx] ml-[15rpx]">{{ detail.taker_mobile }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[24rpx] mt-[12rpx] leading-[26rpx]">{{ detail.taker_full_address }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin card-template p-[0] py-[var(--pad-top-m)] overflow-hidden" :class="{'pb-[var(--pad-top-m)]': detail.gift_goods.length <= 0}" :style="detail.delivery_type == 'virtual' ? 'margin-top: -86rpx' : 'margin-top: 20rpx'">
|
|
||||||
<view v-for="(goodsItem, goodsIndex) in detail.goods" :key="goodsIndex" class="px-[var(--pad-sidebar-m)]">
|
|
||||||
<view class="order-goods-item flex justify-between flex-wrap mb-[20rpx]">
|
|
||||||
<view class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" @click="goodsEvent(goodsItem.goods_id)">
|
|
||||||
<u--image class="overflow-hidden" radius="var(--goods-rounded-big)" width="150rpx" height="150rpx"
|
|
||||||
:src="img(goodsItem.goods_image_thumb_small ? goodsItem.goods_image_thumb_small : '')"
|
|
||||||
model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image
|
|
||||||
class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden"
|
|
||||||
:src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill">
|
|
||||||
</image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
|
|
||||||
<view>
|
|
||||||
<view class="text-[28rpx] max-w-[490rpx] truncate leading-[40rpx] text-[#333]">{{ goodsItem.goods_name }}</view>
|
|
||||||
<view v-if="goodsItem.sku_name">
|
|
||||||
<view class="text-[22rpx] mt-[14rpx] text-[var(--text-color-light9)] truncate max-w-[490rpx] leading-[28rpx]">
|
|
||||||
{{ goodsItem.sku_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="goodsItem.manjian_info && Object.keys(goodsItem.manjian_info).length" class="flex items-center mt-[10rpx] mb-[auto]" @click.stop="manjianOpenFn(goodsItem.manjian_info)">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[20rpx] flex items-center justify-center w-[88rpx] h-[36rpx] mr-[6rpx]">满减送</view>
|
|
||||||
<text class="text-[22rpx] text-[#999]">{{goodsItem.manjian_info.manjian_name}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-baseline leading-[28rpx] text-[#333]">
|
|
||||||
<view class="price-font">
|
|
||||||
<view class="text-[40rpx] inline-block" v-if="goodsItem.extend && parseFloat(goodsItem.extend.point) > 0">
|
|
||||||
<text class="text-[40rpx] font-200">{{goodsItem.extend.point}}</text>
|
|
||||||
<text class="text-[32rpx] ml-[4rpx]">积分</text>
|
|
||||||
</view>
|
|
||||||
<text class="mx-[4rpx] text-[32rpx]" v-if="parseFloat(goodsItem.price) && goodsItem.extend && parseFloat(goodsItem.extend.point) > 0">+</text>
|
|
||||||
<block v-if="parseFloat(goodsItem.price) && goodsItem.extend && parseFloat(goodsItem.extend.point) > 0">
|
|
||||||
<text class="text-[40rpx] font-200">{{ parseFloat(goodsItem.price).toFixed(2) }}</text>
|
|
||||||
<text class="text-[32rpx] ml-[4rpx]">元</text>
|
|
||||||
</block>
|
|
||||||
<block v-if="goodsItem.extend && goodsItem.extend && goodsItem.extend.is_newcomer">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(goodsItem.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsItem.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</block>
|
|
||||||
<block v-if="!goodsItem.extend">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(goodsItem.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(goodsItem.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx]">x{{ goodsItem.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center box-border mt-[8rpx]" v-if="goodsItem.extend && goodsItem.extend.is_newcomer && goodsItem.num>1">
|
|
||||||
<image class="h-[24rpx] w-[56rpx]" :src="img('addon/shop/newcomer.png')" mode="heightFix" />
|
|
||||||
<view class="text-[24rpx] text-[#FFB000] leading-[34rpx] ml-[8rpx]">第1{{goodsItem.unit}},¥{{parseFloat(goodsItem.extend.newcomer_price).toFixed(2)}}/{{goodsItem.unit}};第{{goodsItem.num>2?'2~'+goodsItem.num:'2'}}{{goodsItem.unit}},¥{{parseFloat(goodsItem.price).toFixed(2)}}/{{goodsItem.unit}}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end w-[100%] mt-[30rpx]" v-if="(goodsItem.status != '1') || (goodsItem.is_enable_refund == 1)">
|
|
||||||
<view v-if="goodsItem.status != '1'"
|
|
||||||
class="text-[22rpx] text-[#303133] leading-[50rpx] px-[20rpx] border-[2rpx] border-solid border-[#999] rounded-full"
|
|
||||||
@click="redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : goodsItem.order_refund_no } })">
|
|
||||||
查看退款</view>
|
|
||||||
<view v-else-if="goodsItem.is_enable_refund == 1"
|
|
||||||
class="text-[22rpx] text-[#303133] leading-[50rpx] px-[20rpx] border-[2rpx] border-solid border-[#999] rounded-full ml-[20rpx]"
|
|
||||||
@click="applyRefund(goodsItem.order_goods_id)">申请退款</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="pt-[20rpx] bg-[#f9f9f9] mt-[20rpx] mx-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)]" v-if="detail.gift_goods.length">
|
|
||||||
<view class="order-goods-item flex justify-between flex-wrap px-[var(--pad-sidebar-m)] pb-[20rpx]" v-for="(goodsItem, goodsIndex) in detail.gift_goods" :key="goodsIndex">
|
|
||||||
<view class="w-[120rpx] h-[120rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" @click="goodsEvent(goodsItem.goods_id)">
|
|
||||||
<u--image class="overflow-hidden" radius="var(--goods-rounded-big)" width="120rpx" height="120rpx"
|
|
||||||
:src="img(goodsItem.goods_image_thumb_small ? goodsItem.goods_image_thumb_small : '')"
|
|
||||||
model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image
|
|
||||||
class="w-[120rpx] h-[120rpx] rounded-[var(--goods-rounded-big)] overflow-hidden"
|
|
||||||
:src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill">
|
|
||||||
</image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[16rpx] py-[8rpx] flex flex-1 flex-col justify-between">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="bg-[var(--primary-color-light)] whitespace-nowrap text-[var(--primary-color)] rounded-[6rpx] text-[22rpx] flex items-center justify-center w-[64rpx] h-[34rpx] mr-[6rpx]">赠品</view>
|
|
||||||
<view class="text-[26rpx] max-w-[400rpx] truncate leading-[40rpx] text-[#333]">{{ goodsItem.goods_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view v-if="goodsItem.sku_name" class="text-[22rpx] text-[var(--text-color-light9)] truncate max-w-[400rpx] leading-[28rpx]">
|
|
||||||
{{ goodsItem.sku_name }}
|
|
||||||
</view>
|
|
||||||
<view class="ml-[auto] font-400 text-[26rpx] text-[#303133]">
|
|
||||||
<text>x</text>
|
|
||||||
<text>{{ goodsItem.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template">
|
|
||||||
<view class="justify-between card-template-item">
|
|
||||||
<view class="text-[28rpx]">{{ t('orderNo') }}</view>
|
|
||||||
<view class="flex items-center text-[28rpx]">
|
|
||||||
<text>{{ detail.order_no }}</text>
|
|
||||||
<text class="w-[2rpx] h-[20rpx] bg-[#999] mx-[10rpx]"></text>
|
|
||||||
<text class="text-[#EF900A]" @click="copy(detail.order_no)">复制</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="detail.out_trade_no" class="justify-between card-template-item">
|
|
||||||
<view class="text-[28rpx]">{{ t('orderTradeNo') }}</view>
|
|
||||||
<view class="text-[28rpx]">{{ detail.out_trade_no }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between card-template-item">
|
|
||||||
<view class="text-[28rpx]">{{ t('createTime') }}</view>
|
|
||||||
<view class="text-[28rpx]">{{ detail.create_time }}</view>
|
|
||||||
</view>
|
|
||||||
<view class=" card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">{{ t('deliveryType') }}</view>
|
|
||||||
<view class="text-[28rpx]">{{ detail.delivery_type_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="detail.pay" class=" card-template-item justify-between !mb-[18rpx]">
|
|
||||||
<view class="text-[28rpx]">{{ t('payTypeName') }}</view>
|
|
||||||
<view class="text-[28rpx]">{{ detail.pay.type_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="detail.pay && detail.member_id !== detail.pay.main_id && detail.pay.status == 2 " class="card-template-item justify-end">
|
|
||||||
<view class="friend-pay relative px-[20rpx] py-[12rpx] bg-[#F2F2F2] rounded-[10rpx] flex items-center">
|
|
||||||
<u-avatar :src="img(detail.pay.pay_member_headimg)" size="20" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" />
|
|
||||||
<text class="ml-[14rpx] text-[24rpx] using-hidden">{{ detail.pay.pay_member }}{{ t('helpPay') }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="detail.pay" class=" card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">{{ t('payTime') }}</view>
|
|
||||||
<view class="text-[28rpx]">{{ detail.pay.pay_time }}</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<!-- 核销码 -->
|
|
||||||
<block v-if="isShowVerify">
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template" v-if="verifyInfo && verifyInfo.length">
|
|
||||||
<swiper class="h-[450rpx]" circular indicator-dots="true" v-if="verifyInfo.length > 1">
|
|
||||||
<swiper-item v-for="(item,index) in verifyInfo" :key="index">
|
|
||||||
<view class="flex flex-col items-center justify-center">
|
|
||||||
<image :src="item.qrcode" class="w-[300rpx] h-[auto]" mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-center mt-[30rpx]">
|
|
||||||
<text class="text-[28rpx] font-500">{{item.code}}</text>
|
|
||||||
<text
|
|
||||||
class="text-[var(--text-color-light6)] text-[24rpx] ml-[10rpx] border-[2rpx] border-solid border-[#666] bg-[#f7f7f7] px-[12rpx] py-[6rpx] rounded"
|
|
||||||
@click="copy(item.code)">复制</text>
|
|
||||||
</view>
|
|
||||||
</swiper-item>
|
|
||||||
</swiper>
|
|
||||||
<block v-else>
|
|
||||||
<view class="flex flex-col items-center justify-center">
|
|
||||||
<image :src="verifyInfo[0].qrcode" class="w-[300rpx] h-[auto]" mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-center mt-[30rpx]">
|
|
||||||
<text class="text-[28rpx] font-500">{{verifyInfo[0].code}}</text>
|
|
||||||
<text
|
|
||||||
class="text-[var(--text-color-light6)] text-[24rpx] ml-[10rpx] border-[2rpx] border-solid border-[#666] bg-[#f7f7f7] px-[12rpx] py-[6rpx] rounded"
|
|
||||||
@click="copy(verifyInfo[0].code)">复制</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template">
|
|
||||||
<view class="title">核销信息</view>
|
|
||||||
<view class="card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">核销次数</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
{{'剩余'+(verifyGoodsData.num - verifyGoodsData.verify_count)+'次'}}/{{'共'+verifyGoodsData.num+'次'}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">有效期</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
{{verifyGoodsData.verify_expire_time ? verifyGoodsData.verify_expire_time : '永久'}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template">
|
|
||||||
<view class="card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">{{ t('goodsMoney') }}</view>
|
|
||||||
<view class="price-font font-500">
|
|
||||||
<text v-if="parseFloat(detail.point) > 0" class="text-[28rpx]">{{detail.point}}积分</text>
|
|
||||||
<text v-if="parseFloat(detail.point) > 0 && parseFloat(detail.goods_money)" class="mx-[4rpx] text-[28rpx]">+</text>
|
|
||||||
<block v-if="parseFloat(detail.goods_money) || !parseFloat(detail.point)">
|
|
||||||
<text class="text-[28rpx]">¥</text>
|
|
||||||
<text class="text-[28rpx]">{{ parseFloat(detail.goods_money).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[28rpx]">.{{ parseFloat(detail.goods_money).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class=" card-template-item justify-between" v-if="parseFloat(detail.delivery_money)">
|
|
||||||
<view class="text-[28rpx]">{{ t('deliveryMoney') }}</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
¥{{ parseFloat(detail.delivery_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- <view class=" card-template-item justify-between">
|
|
||||||
<view class="text-[28rpx]">{{ t('discountMoney') }}</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
-¥{{ parseFloat(detail.discount_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
<view class=" card-template-item justify-between" v-if="parseFloat(detail.coupon_money)">
|
|
||||||
<view class="text-[28rpx]">优惠券优惠</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
-¥{{ parseFloat(detail.coupon_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class=" card-template-item justify-between" v-if="parseFloat(detail.manjian_discount_money)">
|
|
||||||
<view class="text-[28rpx]">满减优惠</view>
|
|
||||||
<view class="price-font font-500 text-[28rpx]">
|
|
||||||
-¥{{ parseFloat(detail.manjian_discount_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class=" card-template-item justify-between items-baseline">
|
|
||||||
<view class="text-[28rpx]">{{ t('orderMoney') }}</view>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font">
|
|
||||||
<text v-if="parseFloat(detail.point) > 0" class="text-[28rpx]">{{detail.point}}积分</text>
|
|
||||||
<text v-if="parseFloat(detail.point) > 0 && parseFloat(detail.order_money)" class="mx-[4rpx] text-[28rpx]">+</text>
|
|
||||||
<text v-if="parseFloat(detail.order_money) || !parseFloat(detail.point)" class="text-[28rpx]">¥{{ parseFloat(detail.order_money).toFixed(2) }} </text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="flex z-2 justify-between items-center bg-[#fff] fixed left-0 right-0 bottom-0 min-h-[100rpx] pl-[30rpx] pr-[20rpx] flex-wrap pb-ios">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="flex mr-[34rpx] flex-col justify-center items-center" @click="orderBtnFn('index')">
|
|
||||||
<view class="nc-iconfont nc-icon-shouyeV6xx11 text-[36rpx]"></view>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">{{t('index')}}</text>
|
|
||||||
</view>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view>
|
|
||||||
<nc-contact :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" :send-message-img="sendMessageImg">
|
|
||||||
<view class="flex flex-col justify-center items-center">
|
|
||||||
<view class="w-[36rpx] h-[36rpx] flex-center">
|
|
||||||
<text class="nc-iconfont nc-icon-kefuV6xx-1 text-[34rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">客服</text>
|
|
||||||
</view>
|
|
||||||
</nc-contact>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end">
|
|
||||||
<view class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#999] rounded-full ml-[20rpx] text-[var(--text-color-light6)]"
|
|
||||||
@click="orderBtnFn('logistics')" v-if="showLogistics(detail)">
|
|
||||||
{{ t('logisticsTracking') }}
|
|
||||||
</view>
|
|
||||||
<view class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center text-center border-[2rpx] border-solid border-[#999] rounded-full ml-[20rpx] text-[var(--text-color-light6)]"
|
|
||||||
v-if="detail.status == 1" @click="orderBtnFn('close')">{{ t('orderClose') }}</view>
|
|
||||||
<view class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center text-center text-[#fff] primary-btn-bg rounded-full ml-[20rpx]"
|
|
||||||
v-if="detail.status == 1" @click="orderBtnFn('pay')">{{ t('topay') }}</view>
|
|
||||||
<view v-if="detail.status == 3"
|
|
||||||
class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center text-center text-[#fff] primary-btn-bg rounded-full ml-[20rpx]"
|
|
||||||
@click="orderBtnFn('finish')">{{ t('orderFinish') }}</view>
|
|
||||||
<block v-if="detail.status == 5 && isShowEvaluate">
|
|
||||||
<view
|
|
||||||
v-if="detail.is_evaluate == 1 || (detail.is_evaluate != 1 && evaluateConfig.is_evaluate == 1)"
|
|
||||||
class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#999] rounded-full ml-[20rpx] !text-[var(--text-color-light6)]"
|
|
||||||
@click="orderBtnFn('evaluate')">
|
|
||||||
{{ detail.is_evaluate == 1 ? t('selectedEvaluate') : t('evaluate') }}
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="tab-bar-placeholder"></view>
|
|
||||||
<pay ref="payRef" @close="payClose"></pay>
|
|
||||||
<logistics-tracking ref="materialRef"></logistics-tracking>
|
|
||||||
<!-- 满减 -->
|
|
||||||
<ns-goods-manjian ref="manjianShowRef"></ns-goods-manjian>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, computed,nextTick } from 'vue';
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect, copy, goback } from '@/utils/common';
|
|
||||||
import { getShopOrderDetail, orderClose, orderFinish } from '@/addon/shop/api/order';
|
|
||||||
import { getEvaluateConfig } from '@/addon/shop/api/shop';
|
|
||||||
import { getVerifyCode } from '@/app/api/verify';
|
|
||||||
import logisticsTracking from '@/addon/shop/pages/order/components/logistics-tracking/logistics-tracking.vue'
|
|
||||||
import useConfigStore from "@/stores/config";
|
|
||||||
import nsGoodsManjian from '@/addon/shop/components/ns-goods-manjian/ns-goods-manjian.vue';
|
|
||||||
import { topTabar } from '@/utils/topTabbar';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let topTabbarData = topTabarObj.setTopTabbarParam({ title: '订单详情' })
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
const detail: any = ref<Object>({});
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
const type = ref('')
|
|
||||||
const orderId = ref('')
|
|
||||||
const orderStepsShow = ref(false)
|
|
||||||
const evaluateConfig = ref<Object>({});
|
|
||||||
const isShowEvaluate = ref(true)
|
|
||||||
const manjianShowRef: any = ref(null); //满减送
|
|
||||||
|
|
||||||
const sendMessageTitle = ref('')
|
|
||||||
const sendMessagePath = ref('')
|
|
||||||
const sendMessageImg = ref('')
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
if(option.order_id){
|
|
||||||
orderId.value = option.order_id;
|
|
||||||
orderDetailFn(orderId.value);
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/order/list',
|
|
||||||
title: '缺少订单id'
|
|
||||||
};
|
|
||||||
goback(parameter)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getEvaluateConfig().then(({ data }) => {
|
|
||||||
evaluateConfig.value = data
|
|
||||||
})
|
|
||||||
|
|
||||||
const orderDetailFn = (id: any) => {
|
|
||||||
loading.value = true;
|
|
||||||
getShopOrderDetail(id).then((res: any) => {
|
|
||||||
detail.value = res.data;
|
|
||||||
if (res.data.order_goods && res.data.order_goods.length && isShowVerify.value) {
|
|
||||||
let obj: any = {};
|
|
||||||
obj.order_goods_id = res.data.order_goods[0].order_goods_id
|
|
||||||
getVerifyCodeFn(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
detail.value.goods = []; //购买商品
|
|
||||||
detail.value.gift_goods = []; //赠品
|
|
||||||
detail.value.order_goods.forEach((item,index)=>{
|
|
||||||
if(item.is_gift){
|
|
||||||
detail.value.gift_goods.push(item);
|
|
||||||
}else{
|
|
||||||
detail.value.goods.push(item);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let evaluateCount = 0;
|
|
||||||
for (let i = 0; i < detail.value.order_goods.length; i++) {
|
|
||||||
if (detail.value.order_goods[i].status != 1 || detail.value.order_goods[i].is_enable_refund == 1) {
|
|
||||||
evaluateCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evaluateCount == detail.value.order_goods.length) {
|
|
||||||
isShowEvaluate.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessageTitle.value = detail.value.order_goods[0].goods_name
|
|
||||||
sendMessageImg.value = img(detail.value.order_goods[0].goods_image_thumb_small || '')
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 满减
|
|
||||||
const manjianOpenFn = (data:any) =>{
|
|
||||||
let obj = {};
|
|
||||||
obj.condition_type = cloneDeep(data).condition_type;
|
|
||||||
obj.rule_json = [cloneDeep(data).rule];
|
|
||||||
obj.name = cloneDeep(data).manjian_name;
|
|
||||||
manjianShowRef.value.open(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
//关闭订单
|
|
||||||
const close = (item : any) => {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定要关闭该订单吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderClose(item.order_id).then((data) => {
|
|
||||||
orderDetailFn(item.order_id);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//订单完成
|
|
||||||
const finish = (item : any) => {
|
|
||||||
// 如果不在微信小程序中
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
orderDetailFn(item.order_id);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 检测微信小程序是否已开通发货信息管理服务
|
|
||||||
if (item.pay && item.pay.type == 'wechatpay' && item.is_trade_managed && wx.openBusinessView) {
|
|
||||||
wx.openBusinessView({
|
|
||||||
businessType: 'weappOrderConfirm',
|
|
||||||
extraData: {
|
|
||||||
merchant_id: item.mch_id,
|
|
||||||
merchant_trade_no: item.out_trade_no
|
|
||||||
},
|
|
||||||
success: (res : any) => {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
orderDetailFn(item.order_id);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: (res : any) => {
|
|
||||||
console.log('小程序确认收货组件打开失败 fail', res);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
orderDetailFn(item.order_id);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsEvent = (id : number) => {
|
|
||||||
if (detail.value.activity_type == 'exchange') {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/point/detail',
|
|
||||||
param: {
|
|
||||||
id: detail.value.relate_id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/goods/detail',
|
|
||||||
param: {
|
|
||||||
goods_id: id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const payRef = ref(null)
|
|
||||||
const materialRef: any = ref(null)
|
|
||||||
const orderBtnFn = (type = '') => {
|
|
||||||
if (type == 'pay')
|
|
||||||
payRef.value?.open(detail.value.order_type, detail.value.order_id, `/addon/shop/pages/order/detail?order_id=${detail.value.order_id}`);
|
|
||||||
else if (type == 'close') {
|
|
||||||
close(detail.value);
|
|
||||||
} else if (type == 'finish') {
|
|
||||||
finish(detail.value);
|
|
||||||
} else if (type == 'index') {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/index',
|
|
||||||
mode: 'reLaunch'
|
|
||||||
});
|
|
||||||
} else if (type == 'logistics') {
|
|
||||||
if (detail.value.order_delivery.length > 0) {
|
|
||||||
let params = {
|
|
||||||
id: detail.value.order_delivery[0].id,
|
|
||||||
mobile: detail.value.taker_mobile
|
|
||||||
}
|
|
||||||
let list : any = []
|
|
||||||
detail.value.order_delivery.forEach((item : any, index : number) => {
|
|
||||||
item.name = `包裹${index + 1}`
|
|
||||||
list.push(item)
|
|
||||||
})
|
|
||||||
|
|
||||||
materialRef.value.open(params);
|
|
||||||
materialRef.value.packageList = list
|
|
||||||
}
|
|
||||||
} else if (type == 'evaluate') {
|
|
||||||
if (!detail.value.is_evaluate) {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate', param: { order_id: detail.value.order_id } })
|
|
||||||
} else {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate_view', param: { order_id: detail.value.order_id } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const dateFormat = (res: any, type: any) => {
|
|
||||||
let data;
|
|
||||||
if (res.indexOf('/') != -1) {
|
|
||||||
data = res.split("/");
|
|
||||||
} else if (res.indexOf('-') != -1) {
|
|
||||||
data = res.split("-");
|
|
||||||
}
|
|
||||||
|
|
||||||
let time;
|
|
||||||
const index = new Date(res).getDay();
|
|
||||||
const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
|
|
||||||
if (type == "yearMonthDay") {
|
|
||||||
time = data[0] + '年' + data[1] + '月' + data[2] + '日';
|
|
||||||
} else if (type == "yearMonthDayWeek") {
|
|
||||||
time = data[0] + '年' + data[1] + '月' + data[2] + '日 ' + week[index];
|
|
||||||
} else if (type == "monthDayWeek") {
|
|
||||||
time = data[1] + '月' + data[2] + '日 ' + week[index];
|
|
||||||
} else {
|
|
||||||
time = data[1] + '月' + data[2] + '日';
|
|
||||||
}
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
const applyRefund = (orderGoodsId : number) => {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/refund/apply',
|
|
||||||
param: {
|
|
||||||
order_id: detail.value.order_id,
|
|
||||||
order_goods_id: orderGoodsId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAddress = () => {
|
|
||||||
uni.openLocation({
|
|
||||||
latitude: Number(detail.value.taker_latitude),
|
|
||||||
longitude: Number(detail.value.taker_longitude),
|
|
||||||
success: function () { }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const showLogistics = (data : any) => {
|
|
||||||
let status = false
|
|
||||||
if (data.delivery_type != 'express') return false;
|
|
||||||
for (let i = 0; i < data.order_delivery.length; i++) {
|
|
||||||
let item = data.order_delivery[i];
|
|
||||||
if (item.sub_delivery_type === 'express' && data.status === '3') {
|
|
||||||
status = true;
|
|
||||||
break;
|
|
||||||
} else if (item.sub_delivery_type === 'express' && data.status === '5') {
|
|
||||||
status = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
status = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return status
|
|
||||||
}
|
|
||||||
|
|
||||||
/************ 虚拟商品核销-start ***************/
|
|
||||||
const verifyGoodsData = ref({}) //虚拟商品
|
|
||||||
const isShowVerify = computed(() => {
|
|
||||||
let bool = false;
|
|
||||||
if(detail.value.order_goods.length == 1){
|
|
||||||
verifyGoodsData.value = detail.value.order_goods[0]
|
|
||||||
|
|
||||||
let data = detail.value.order_goods[0];
|
|
||||||
bool = data.is_verify == 1 && data.goods_type == 'virtual' && data.delivery_status == 'delivery_finish' && detail.value.status == 3 ? true : false;
|
|
||||||
}
|
|
||||||
return bool
|
|
||||||
})
|
|
||||||
const verifyInfo = ref([])
|
|
||||||
const getVerifyCodeFn = (data:any) => {
|
|
||||||
verifyInfo.value = [];
|
|
||||||
|
|
||||||
getVerifyCode('shopVirtualGoods', data).then((res: any) => {
|
|
||||||
verifyInfo.value = res.data;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/************ 虚拟商品核销-end ***************/
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-item {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-goods-item:nth-child(1) {
|
|
||||||
margin-top: 0rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-linear {
|
|
||||||
background: linear-gradient(94deg, #F84949 8%, #FF9A68 99%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.triangle {
|
|
||||||
@apply relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
@apply absolute;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
position: absolute;
|
|
||||||
bottom: -40rpx;
|
|
||||||
border: 20rpx solid #EEF3FF;
|
|
||||||
border-left-color: transparent;
|
|
||||||
border-right-color: transparent;
|
|
||||||
border-bottom-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-bar-placeholder {
|
|
||||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 100rpx);
|
|
||||||
padding-bottom: calc(env(safe-area-inset-bottom) + 100rpx);
|
|
||||||
}
|
|
||||||
:deep(.u-image__error){
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
.friend-pay{
|
|
||||||
&::after{
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 20rpx;
|
|
||||||
height: 20rpx;
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
position: absolute;
|
|
||||||
right: 30rpx;
|
|
||||||
top: 0;
|
|
||||||
transform: translateY(-50%) rotate(45deg);
|
|
||||||
border-radius: 4rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,329 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden order-list" :style="themeColor()">
|
|
||||||
<view class="fixed left-0 top-0 right-0 z-10" v-if="statusLoading">
|
|
||||||
<scroll-view :scroll-x="true" class="tab-style-2">
|
|
||||||
<view class="tab-content">
|
|
||||||
<view class="tab-items" :class="{ 'class-select': orderState === item.status.toString() }" @click="orderStateFn(item.status)" v-for="(item, index) in orderStateList">{{ item.name }}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<mescroll-body ref="mescrollRef" top="88rpx" @init="mescrollInit" :down="{ use: false }" @up="getShopOrderFn">
|
|
||||||
<view class="sidebar-margin pt-[var(--top-m)]" v-if="list.length">
|
|
||||||
<template v-for="(item, index) in list" :key="index">
|
|
||||||
<view class="mb-[var(--top-m)] card-template">
|
|
||||||
<view @click.stop="toLink(item)">
|
|
||||||
<view class="flex justify-between items-center">
|
|
||||||
<view class="text-[#303133] text-[26rpx] font-400 leading-[36rpx]">
|
|
||||||
<text>{{ t('orderNo') }}:</text>
|
|
||||||
<text class="ml-[10rpx]">{{ item.order_no }}</text>
|
|
||||||
<text class="text-[#303133] text-[26rpx] font-400 nc-iconfont nc-icon-fuzhiV6xx1 ml-[11rpx]" @click.stop="copy(item.order_no)"></text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#303133] text-[26rpx] leading-[34rpx]" :class="{'text-primary': item.status == 1,'!text-[var(--text-color-light9)]' :item.status == 5 || item.status == -1}">{{ item.status_name.name }}</view>
|
|
||||||
</view>
|
|
||||||
<block v-for="(subItem, index) in item.order_goods" :key="index">
|
|
||||||
<view class="flex box-border mt-[20rpx]">
|
|
||||||
<u--image width="150rpx" height="150rpx" :radius="'var(--goods-rounded-big)'" :src="img(subItem.goods_image_thumb_small ? subItem.goods_image_thumb_small : '')" mode="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col box-border">
|
|
||||||
<view class="flex justify-between items-baseline">
|
|
||||||
<view class="max-w-[322rpx] text-[28rpx] leading-[40rpx] font-400 truncate text-[#303133]">{{ subItem.goods_name }}</view>
|
|
||||||
<block v-if="item.activity_type == 'exchange'">
|
|
||||||
<view class="text-right ml-[10rpx] leading-[42rpx]" v-if="parseFloat(subItem.price)">
|
|
||||||
<text class="text-[22rpx] font-400 price-font">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500 price-font">{{parseFloat(subItem.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500 price-font">.{{parseFloat(subItem.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<view class="text-right leading-[42rpx] ml-[10rpx]">
|
|
||||||
<text class="text-[22rpx] price-font">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500 price-font">{{parseFloat(subItem.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500 price-font">.{{parseFloat(subItem.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-baseline text-[#303133] mt-[14rpx]">
|
|
||||||
<view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] font-400 truncate leading-[34rpx] max-w-[369rpx] mb-[10rpx]" v-if="subItem.sku_name">{{ subItem.sku_name }}</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx] text-[var(--text-color-light6)]" v-if="item.delivery_type != 'virtual'">
|
|
||||||
{{t('deliveryType') }} : {{item.delivery_type_name}}
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx] text-[var(--text-color-light6)]" v-else>{{t('createTime') }} :{{item.create_time}}</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx] font-400 w-[90rpx] leading-[36rpx]">x{{ subItem.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center box-border mt-[8rpx]" v-if="subItem.extend && subItem.extend.is_newcomer && subItem.num > 1">
|
|
||||||
<image class="h-[24rpx] w-[56rpx]" :src="img('addon/shop/newcomer.png')" mode="heightFix" />
|
|
||||||
<view class="text-[24rpx] text-[#FFB000] leading-[34rpx] ml-[8rpx]">第1{{subItem.unit}},¥{{parseFloat(subItem.extend.newcomer_price).toFixed(2)}}/{{subItem.unit}};第{{subItem.num>2?'2~'+subItem.num:'2'}}{{subItem.unit}},¥{{parseFloat(subItem.price).toFixed(2)}}/{{subItem.unit}}</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end items-center mt-[20rpx]">
|
|
||||||
<view class="flex items-baseline">
|
|
||||||
<view class="text-[22rpx] text-[var(--text-color-light9)] leading-[30rpx] mr-[6rpx]" v-if="parseFloat(item.delivery_money)">{{ t('service') }}</view>
|
|
||||||
<view class="text-[22rpx] font-400 leading-[30rpx] text-[#303133]">{{ t('actualPayment') }}:</view>
|
|
||||||
<view class="leading-[1] text-[var(--price-text-color)]">
|
|
||||||
<block v-if="item.activity_type == 'exchange'">
|
|
||||||
<text class="text-[36rpx] mr-[2rpx] leading-[40rpx] price-font font-500">{{ item.point }}</text>
|
|
||||||
<text class="text-[20rpx] leading-[28rpx] font-500">{{ t('point') }}</text>
|
|
||||||
<block v-if="parseFloat(item.order_money)">
|
|
||||||
<text class="text-[20rpx] mx-[4rpx] font-500 leading-[28rpx]">+</text>
|
|
||||||
<text class="text-[36rpx] font-500 leading-[40rpx] price-font">{{ parseFloat(item.order_money).toFixed(2) }}</text>
|
|
||||||
<text class="text-[20rpx] font-500 leading-[28rpx] ml-[2rpx]">{{ t('money') }}</text>
|
|
||||||
</block>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<text class="text-[22rpx] leading-[26rpx] price-font">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500 leading-[40rpx] price-font">{{ parseFloat(item.order_money).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500 leading-[28rpx] price-font">.{{ parseFloat(item.order_money).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end text-[28rpx] mt-[20rpx] items-center" v-if="(item.status == 1) || (item.status == 3) || (item.status == 5 && item.is_show_evaluate && evaluateConfig.is_evaluate == 1)">
|
|
||||||
<view class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full text-[var(--text-color-light6)] box-border" v-if="item.status == 1" @click.stop="orderBtnFn(item, 'close')">{{ t('orderClose') }}</view>
|
|
||||||
<view class="text-[24rpx] font-500 flex-center h-[56rpx] min-w-[150rpx] text-center border-[0] text-[#fff] primary-btn-bg rounded-full ml-[20rpx] box-border" v-if="item.status == 1" @click.stop="orderBtnFn(item, 'pay')">{{ t('topay') }}</view>
|
|
||||||
<view class="text-[24rpx] font-500 flex-center h-[56rpx] min-w-[150rpx] text-center border-[0] text-[#fff] primary-btn-bg rounded-full ml-[20rpx] box-border" v-if="item.status == 3" @click.stop="orderBtnFn(item, 'finish')">{{ t('orderFinish') }}</view>
|
|
||||||
<view class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx] text-[var(--text-color-light6)] box-border" v-if="item.status == 5 && item.is_show_evaluate && evaluateConfig.is_evaluate == 1" @click.stop="orderBtnFn(item, 'evaluate')">{{ item.is_evaluate == 1 ? t('selectedEvaluate') : t('evaluate') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!list.length && loading" :option="{tip : '暂无订单'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<pay ref="payRef" @close="payClose"></pay>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref,nextTick } from 'vue';
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect,copy } from '@/utils/common'
|
|
||||||
import { getShopOrderStatus, getShopOrder, orderClose, orderFinish } from '@/addon/shop/api/order';
|
|
||||||
import { getEvaluateConfig } from '@/addon/shop/api/shop';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onLoad, onPageScroll, onReachBottom, onShow } from '@dcloudio/uni-app';
|
|
||||||
import useConfigStore from "@/stores/config";
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const statusLoading = ref<boolean>(false);
|
|
||||||
const orderState = ref('')
|
|
||||||
const orderStateList: any = ref([]);
|
|
||||||
const evaluateConfig = ref("")
|
|
||||||
|
|
||||||
const mch_id = ref('')
|
|
||||||
const isTradeManaged = ref(false)
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
orderState.value = option.status || "";
|
|
||||||
evaluateEvent()
|
|
||||||
getShopOrderStatusFn();
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
nextTick(()=>{
|
|
||||||
// 评价完成之后,会返回到订单列表,需要请求最新数据
|
|
||||||
if(getMescroll()){ getMescroll().resetUpScroll();}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const evaluateEvent = () => {
|
|
||||||
getEvaluateConfig().then((data: any) => {
|
|
||||||
evaluateConfig.value = data.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getShopOrderFn = (mescroll: any) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
status: orderState.value
|
|
||||||
};
|
|
||||||
|
|
||||||
getShopOrder(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
|
|
||||||
newArr.forEach((item:any)=> {
|
|
||||||
item.is_show_evaluate = true;
|
|
||||||
let evaluateCount = 0;
|
|
||||||
for (let i = 0; i < item.order_goods.length; i++) {
|
|
||||||
if (item.order_goods[i].status != 1 || item.order_goods[i].is_enable_refund == 1) {
|
|
||||||
evaluateCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (evaluateCount == item.order_goods.length) {
|
|
||||||
item.is_show_evaluate = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
|
|
||||||
mch_id.value = res.data.mch_id;
|
|
||||||
isTradeManaged.value = res.data.is_trade_managed;
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getShopOrderStatusFn = () => {
|
|
||||||
statusLoading.value = false;
|
|
||||||
orderStateList.value = [];
|
|
||||||
let obj = { name: '全部', status: '' };
|
|
||||||
orderStateList.value.push(obj);
|
|
||||||
|
|
||||||
getShopOrderStatus().then((res: any) => {
|
|
||||||
Object.values(res.data).forEach((item, index) => {
|
|
||||||
orderStateList.value.push(item);
|
|
||||||
});
|
|
||||||
statusLoading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
statusLoading.value = true;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const orderStateFn = (status: any) => {
|
|
||||||
orderState.value = status.toString();
|
|
||||||
list.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
};
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: data.order_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付
|
|
||||||
const payRef = ref(null)
|
|
||||||
const orderBtnFn = (data: any, type = '') => {
|
|
||||||
if (type == 'pay')
|
|
||||||
payRef.value?.open(data.order_type, data.order_id, `/addon/shop/pages/order/detail?order_id=${data.order_id}`);
|
|
||||||
else if (type == 'close') {
|
|
||||||
close(data);
|
|
||||||
} else if (type == 'finish') {
|
|
||||||
finish(data);
|
|
||||||
} else if (type == 'evaluate') {
|
|
||||||
if (!data.is_evaluate) {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate', param: { order_id: data.order_id } })
|
|
||||||
} else {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate_view', param: { order_id: data.order_id } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//关闭订单
|
|
||||||
const close = (item: any) => {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定要关闭该订单吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderClose(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//订单完成
|
|
||||||
const finish = (item: any) => {
|
|
||||||
// 如果不在微信小程序中
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 检测微信小程序是否已开通发货信息管理服务
|
|
||||||
if (item.pay && item.pay.type == 'wechatpay' && isTradeManaged.value && wx.openBusinessView) {
|
|
||||||
wx.openBusinessView({
|
|
||||||
businessType: 'weappOrderConfirm',
|
|
||||||
extraData: {
|
|
||||||
merchant_id: mch_id.value,
|
|
||||||
merchant_trade_no: item.out_trade_no
|
|
||||||
},
|
|
||||||
success: (res:any) => {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: (res:any) => {
|
|
||||||
console.log('小程序确认收货组件打开失败 fail', res);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.order-list .mescroll-body {
|
|
||||||
padding-bottom: constant(safe-area-inset-bottom) !important;
|
|
||||||
padding-bottom: env(safe-area-inset-bottom) !important;
|
|
||||||
}
|
|
||||||
.order-list :deep(.u-count-down__text){
|
|
||||||
font-size: 24rpx !important;
|
|
||||||
color:#EF000C !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,516 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh]" v-if="orderData">
|
|
||||||
<view class="pt-[30rpx] sidebar-margin payment-bottom">
|
|
||||||
<!-- 配送方式 -->
|
|
||||||
<view class="mb-[var(--top-m)] rounded-[var(--rounded-big)] bg-white" v-if="orderData.basic.has_goods_types.includes('real') && delivery_type_list.length">
|
|
||||||
<view class="rounded-tl-[var(--rounded-big)] rounded-tr-[var(--rounded-big)] head-tab flex items-center w-full bg-[#F1F1F1]" v-if="delivery_type_list.length > 1">
|
|
||||||
<view v-for="(item, index) in delivery_type_list" :key="index" class="head-tab-item flex-1 relative" :class="{'active': index === activeIndex}">
|
|
||||||
<view class="h-[74rpx] relative z-10 text-center leading-[74rpx] text-[28rpx]" @click="switchDeliveryType(item.key, index)">
|
|
||||||
{{ item.name }}
|
|
||||||
</view>
|
|
||||||
<image v-if="index === activeIndex && delivery_type_list.length == 3" class="tab-image absolute bottom-[-2rpx] h-[94rpx] w-[240rpx]" :src="img(`addon/shop/payment/tab_${index}.png`)" mode="aspectFit"></image>
|
|
||||||
<image v-else-if="index === activeIndex && delivery_type_list.length == 2" class="tab-img absolute bottom-[-2rpx] h-[95rpx] w-[354rpx]" :src="img(`addon/shop/payment/tabstyle_${index}.png`)" mode="aspectFit"></image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="min-h-[140rpx] flex items-center px-[30rpx]">
|
|
||||||
<!-- 收货地址 -->
|
|
||||||
<view class="w-full" v-if="['express', 'local_delivery'].includes(createData.delivery.delivery_type)" @click="toSelectAddress">
|
|
||||||
<view v-if="!$u.test.isEmpty(orderData.delivery.take_address)" class="pt-[20rpx] pb-[30rpx] flex items-center">
|
|
||||||
<image class="w-[60rpx] h-[60rpx] mr-[20rpx] flex-shrink-0" :src="img('addon/shop/payment/position_01.png')" mode="aspectFit"></image>
|
|
||||||
<view class="flex flex-col overflow-hidden">
|
|
||||||
<text class="text-[26rpx] text-[var(--text-color-light9)] mt-[16rpx] truncate max-w-[536rpx]">{{orderData.delivery.take_address.full_address.split(orderData.delivery.take_address.address)[0]}}</text>
|
|
||||||
<text class="font-500 text-[30rpx] mt-[14rpx] text-[#333] truncate max-w-[536rpx]">{{orderData.delivery.take_address.address}}</text>
|
|
||||||
<view class="flex items-center text-[26rpx] text-[var(--text-color-light6)] mt-[16rpx]">
|
|
||||||
<text class="mr-[16rpx]">{{ orderData.delivery.take_address.name }}</text>
|
|
||||||
<text>{{ mobileHide(orderData.delivery.take_address.mobile) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center">
|
|
||||||
<image class="w-[26rpx] h-[30rpx] mr-[10rpx]" :src="img('addon/shop/payment/position_02.png')" mode="aspectFit"></image>
|
|
||||||
<text class="text-[28rpx]">添加收货地址</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)] ml-auto"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 自提点 -->
|
|
||||||
<view class="flex items-center w-full" v-if="createData.delivery.delivery_type == 'store'" @click="storeRef.open()">
|
|
||||||
<view v-if="!$u.test.isEmpty(orderData.delivery.take_store)" class="pt-[40rpx] pb-[30rpx] w-full flex items-center">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[30rpx] font-500 text-[#303133] mb-[20rpx]">{{ orderData.delivery.take_store.store_name }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] mb-[20rpx] leading-[1.4] flex">
|
|
||||||
<text class="flex-shrink-0">门店地址:</text>
|
|
||||||
<text class="max-w-[490rpx]">{{ orderData.delivery.take_store.full_address }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] mb-[20rpx]">
|
|
||||||
<text>联系电话:</text>
|
|
||||||
<text>{{ orderData.delivery.take_store.store_mobile }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)]">
|
|
||||||
<text>营业时间:</text>
|
|
||||||
<text>{{ orderData.delivery.take_store.trade_time }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center w-full">
|
|
||||||
<image class="w-[26rpx] h-[30rpx] mr-[10rpx]" :src="img('addon/shop/payment/position_02.png')" mode="aspectFit"></image>
|
|
||||||
<text class="text-[28rpx]">请选择自提点</text>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="orderData.basic.has_goods_types.includes('real') && !delivery_type_list.length" class="mb-[var(--top-m)] card-template h-[100rpx] flex items-center">
|
|
||||||
<p class="text-[28rpx] text-[var(--primary-color)]">商家尚未配置配送方式</p>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="mb-[var(--top-m)] card-template p-[0] pb-[var(--pad-top-m)]">
|
|
||||||
<view class="py-[var(--pad-top-m)]">
|
|
||||||
<view class="mb-[20rpx] px-[var(--pad-sidebar-m)]" v-for="(item, index) in orderData.goods" :key="index">
|
|
||||||
<view class="flex">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="180rpx" height="180rpx" :src="img(item.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[180rpx] h-[180rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex flex-1 w-0 flex-col justify-between ml-[20rpx] py-[6rpx]">
|
|
||||||
<view class="line-normal">
|
|
||||||
<view class="truncate text-[#303133] text-[28rpx] leading-[32rpx]">
|
|
||||||
{{ item.goods.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view class="mt-[14rpx] flex" v-if="item.sku_name">
|
|
||||||
<text class="truncate text-[24rpx] text-[var(--text-color-light9)] leading-[28rpx]">{{ item.sku_name }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.manjian_info && Object.keys(item.manjian_info).length" class="flex items-center mt-[10rpx] mb-[auto]" @click.stop="manjianOpenFn(item.manjian_info)">
|
|
||||||
<view class="bg-[var(--primary-color-light)] text-[var(--primary-color)] rounded-[6rpx] text-[20rpx] flex items-center justify-center w-[88rpx] h-[36rpx] mr-[6rpx]">满减送</view>
|
|
||||||
<text class="text-[22rpx] text-[#999]">{{item.manjian_info.manjian_name}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="mb-auto" :class="{'mt-[6rpx]': !item.sku_name}" v-if="item.not_support_delivery">
|
|
||||||
<u-alert type="error" description="该商品不支持当前所选配送方式" class="leading-[30rpx] !inline-block" fontSize="11"></u-alert>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-baseline">
|
|
||||||
<view class="text-[var(--price-text-color)] flex items-baseline price-font">
|
|
||||||
<text class="text-[24rpx] font-500 mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(item.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(item.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="font-400 text-[28rpx] text-[#303133]">
|
|
||||||
<text>x</text>
|
|
||||||
<text>{{ item.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center mt-[8rpx]" :class="{'pb-[40rpx]': (index + 1) != Object.keys(orderData.goods_data).length}" v-if="item.is_newcomer && item.newcomer_price != item.price && item.num>1">
|
|
||||||
<image class="h-[24rpx] w-[56rpx]" :src="img('addon/shop/newcomer.png')" mode="heightFix" />
|
|
||||||
<view class="text-[24rpx] text-[#FFB000] leading-[34rpx] ml-[8rpx]"
|
|
||||||
>第1{{item.goods.unit}},¥{{parseFloat(item.newcomer_price).toFixed(2)}}/{{item.goods.unit}};第{{item.num>2?'2~'+item.num:'2'}}{{item.goods.unit}},¥{{parseFloat(item.price).toFixed(2)}}/{{item.goods.unit}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 赠品 -->
|
|
||||||
<view class="pt-[20rpx] bg-[#f9f9f9] mt-[24rpx] mx-[var(--pad-sidebar-m)] rounded-[30rpx]" v-if="orderData.gift_goods && Object.keys(orderData.gift_goods).length">
|
|
||||||
<view v-for="(item, key, index) in orderData.gift_goods" :key="index" class="flex px-[var(--pad-sidebar-m)] pb-[20rpx]">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="120rpx" height="120rpx" :src="img(item.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[120rpx] h-[120rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="ml-[16rpx] py-[8rpx] flex flex-1 flex-col justify-between">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="bg-[var(--primary-color-light)] whitespace-nowrap text-[var(--primary-color)] rounded-[6rpx] text-[22rpx] flex items-center justify-center w-[64rpx] h-[34rpx] mr-[6rpx]">赠品</view>
|
|
||||||
<view class="text-[26rpx] max-w-[400rpx] truncate leading-[40rpx] text-[#333]">{{ item.goods.goods_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view v-if="item.sku_name" class="text-[22rpx] text-[var(--text-color-light9)] truncate max-w-[400rpx] leading-[28rpx]">
|
|
||||||
{{ item.sku_name }}
|
|
||||||
</view>
|
|
||||||
<view class="ml-[auto] font-400 text-[26rpx] text-[#303133]">
|
|
||||||
<text>x</text>
|
|
||||||
<text>{{ item.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 买家留言 -->
|
|
||||||
<view class="bg-white flex items-center leading-[30rpx] px-[var(--pad-sidebar-m)]">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] text-[#303133]">买家留言</view>
|
|
||||||
<view class="flex-1 text-[#303133]">
|
|
||||||
<input type="text" v-model="createData.member_remark" class="text-right text-[#333] text-[28rpx]" maxlength="50" placeholder="请输入留言信息给卖家" placeholder-class="text-[var(--text-color-light9)] text-[28rpx]">
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 发票 -->
|
|
||||||
<view v-if="invoiceRef && invoiceRef.invoiceOpen" class="flex items-center text-[#303133] leading-[30rpx] mt-[30rpx] px-[var(--pad-sidebar-m)]" @click="invoiceRef.open()">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] text-[#303133]">发票信息</view>
|
|
||||||
<view class="flex-1 w-0 text-right truncate">
|
|
||||||
<text class="text-[28rpx] text-[#333]">{{ createData.invoice.header_name || '不需要发票' }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="mb-[var(--top-m)] card-template" v-if="couponRef && couponList.length">
|
|
||||||
<!-- 优惠券 -->
|
|
||||||
<view class="flex items-center h-[40rpx] leading-[40rpx]" @click="couponRef.open(createData.discount.coupon_id)" v-if="couponList.length">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] text-[#303133] flex-shrink-0">优惠券</view>
|
|
||||||
<view class="flex-1 flex justify-end truncate">
|
|
||||||
<text v-if="orderData.discount && orderData.discount.coupon" class="text-[var(--primary-color)] text-[28rpx] truncate ">
|
|
||||||
{{ orderData.discount.coupon.title }}
|
|
||||||
</text>
|
|
||||||
<text class="text-[28rpx] text-gray-subtitle" v-else>请选择优惠券</text>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx -mb-[2rpx] text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="card-template">
|
|
||||||
<view class="title">价格明细</view>
|
|
||||||
<view class="card-template-item">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] leading-[30rpx] text-[#303133]">商品金额</view>
|
|
||||||
<view class="flex-1 w-0 text-right price-font text-[#333] text-[32rpx]">
|
|
||||||
¥{{ parseFloat(orderData.basic.goods_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item" v-if="parseFloat(orderData.basic.delivery_money)">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] leading-[30rpx] text-[#303133]">配送费用</view>
|
|
||||||
<view class="flex-1 w-0 text-right price-font text-[#333] text-[32rpx]">
|
|
||||||
¥{{ parseFloat(orderData.basic.delivery_money).toFixed(2) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- <view class="card-template-item" v-if="orderData.basic.discount_money">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] leading-[30rpx] text-[#303133]">优惠金额</view>
|
|
||||||
<view class="flex-1 w-0 text-right text-[var(--price-text-color)] text-[32rpx] price-font leading-[1]">
|
|
||||||
-¥{{parseFloat(orderData.basic.discount_money)}}
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
<view class="card-template-item" v-if="parseFloat(orderData.basic.coupon_money)">
|
|
||||||
<view class="text-[28rpx] w-[170rpx] leading-[30rpx] text-[#303133]">优惠券优惠</view>
|
|
||||||
<view class="flex-1 w-0 text-right text-[var(--price-text-color)] text-[32rpx] price-font leading-[1]">
|
|
||||||
-¥{{parseFloat(orderData.basic.coupon_money).toFixed(2)}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item" v-if="parseFloat(orderData.basic.manjian_discount_money)">
|
|
||||||
<view class="text-[28rpx] w-[170rpx] leading-[30rpx] text-[#303133]">满减优惠</view>
|
|
||||||
<view class="flex-1 w-0 text-right text-[var(--price-text-color)] text-[32rpx] price-font leading-[1]">
|
|
||||||
-¥{{parseFloat(orderData.basic.manjian_discount_money).toFixed(2)}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" zIndex="10">
|
|
||||||
<view class="flex-1 flex items-center justify-between pl-[30rpx] pr-[20rpx]">
|
|
||||||
<view class="flex items-baseline">
|
|
||||||
<text class="text-[26rpx] text-[#333] leading-[32rpx]">合计:</text>
|
|
||||||
<view class="inline-block">
|
|
||||||
<text class="text-[26rpx] font-500 text-[var(--price-text-color)] price-font leading-[30rpx]">¥</text>
|
|
||||||
<text class="text-[44rpx] font-500 text-[var(--price-text-color)] price-font leading-[46rpx]">{{ parseFloat(orderData.basic.order_money).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[26rpx] font-500 text-[var(--price-text-color)] price-font leading-[46rpx]">.{{ parseFloat(orderData.basic.order_money).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button class="w-[196rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] m-0 rounded-full primary-btn-bg remove-border" hover-class="none" @click="create">提交订单</button>
|
|
||||||
</view>
|
|
||||||
</u-tabbar>
|
|
||||||
|
|
||||||
<!-- 选择优惠券 -->
|
|
||||||
<select-coupon :order-key="createData.order_key" ref="couponRef" @confirm="confirmSelectCoupon" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 选择自提点 -->
|
|
||||||
<select-store ref="storeRef" @confirm="confirmSelectStore" />
|
|
||||||
<!-- 发票 -->
|
|
||||||
<invoice ref="invoiceRef" @confirm="confirmInvoice" />
|
|
||||||
<!-- 地址 -->
|
|
||||||
<address-list ref="addressRef" @confirm="confirmAddress" />
|
|
||||||
<!-- 满减 -->
|
|
||||||
<ns-goods-manjian ref="manjianShowRef"></ns-goods-manjian>
|
|
||||||
<pay ref="payRef" @close="payClose" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, watch, nextTick } from 'vue'
|
|
||||||
import { orderCreateCalculate, orderCreate } from '@/addon/shop/api/order'
|
|
||||||
import { redirect, img, moneyFormat, mobileHide } from '@/utils/common'
|
|
||||||
import selectCoupon from './components/select-coupon/select-coupon'
|
|
||||||
import selectStore from './components/select-store/select-store'
|
|
||||||
import addressList from './components/address-list/address-list'
|
|
||||||
import invoice from './components/invoice/invoice'
|
|
||||||
import nsGoodsManjian from '@/addon/shop/components/ns-goods-manjian/ns-goods-manjian.vue';
|
|
||||||
import { useSubscribeMessage } from '@/hooks/useSubscribeMessage'
|
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
const createData: any = ref({
|
|
||||||
order_key: '',
|
|
||||||
member_remark: '',
|
|
||||||
discount: {},
|
|
||||||
invoice: {},
|
|
||||||
delivery: {
|
|
||||||
delivery_type: ''
|
|
||||||
},
|
|
||||||
extend_data:{} // 扩展数据,目前礼品卡用到
|
|
||||||
})
|
|
||||||
const manjianShowRef: any = ref(null); //满减送
|
|
||||||
|
|
||||||
const orderData: any = ref(null)
|
|
||||||
const couponRef = ref()
|
|
||||||
const storeRef = ref()
|
|
||||||
const payRef = ref()
|
|
||||||
const addressRef = ref()
|
|
||||||
const invoiceRef = ref()
|
|
||||||
const createLoading = ref(false)
|
|
||||||
const activeIndex = ref(0)//配送方式激活
|
|
||||||
const delivery_type_list = ref([])
|
|
||||||
uni.getStorageSync('orderCreateData') && Object.assign(createData.value, uni.getStorageSync('orderCreateData'))
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
nextTick(()=>{
|
|
||||||
if(storeRef.value){
|
|
||||||
storeRef.value.getData((data:any)=>{
|
|
||||||
if(data.length){
|
|
||||||
createData.value.delivery.take_store_id = ((data[0] && data[0].store_id) ? data[0].store_id: 0)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 选择地址之后跳转回来
|
|
||||||
const selectAddress = uni.getStorageSync('selectAddressCallback')
|
|
||||||
if (selectAddress) {
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = selectAddress.delivery
|
|
||||||
createData.value.delivery.take_address_id = selectAddress.address_id
|
|
||||||
uni.removeStorage({ key: 'selectAddressCallback' })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换配送方式
|
|
||||||
const switchDeliveryType = (type: string, index: number) => {
|
|
||||||
if (createData.value.delivery.delivery_type != type) {
|
|
||||||
activeIndex.value = index
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = type
|
|
||||||
createData.value.delivery.take_address_id = 0
|
|
||||||
calculate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 满减
|
|
||||||
const manjianOpenFn = (data:any) =>{
|
|
||||||
let obj = {};
|
|
||||||
obj.condition_type = cloneDeep(data).condition_type;
|
|
||||||
obj.rule_json = [cloneDeep(data).rule];
|
|
||||||
obj.name = cloneDeep(data).manjian_name;
|
|
||||||
manjianShowRef.value.open(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单计算
|
|
||||||
*/
|
|
||||||
const calculate = () => {
|
|
||||||
orderCreateCalculate(createData.value).then(({ data }) => {
|
|
||||||
orderData.value = cloneDeep(data);
|
|
||||||
|
|
||||||
orderData.value.goods = []; //购买商品
|
|
||||||
if(orderData.value.goods_data && Object.values(orderData.value.goods_data).length){
|
|
||||||
Object.values(orderData.value.goods_data).forEach((item,index)=>{
|
|
||||||
orderData.value.goods.push(item);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
createData.value.order_key = data.order_key
|
|
||||||
if (orderData.value.delivery.delivery_type_list) {
|
|
||||||
delivery_type_list.value = Object.values(orderData.value.delivery.delivery_type_list)
|
|
||||||
}
|
|
||||||
if(orderData.value.discount && orderData.value.discount.manjian){
|
|
||||||
orderData.value.manjian = orderData.value.discount.manjian
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectAddress) activeIndex.value = delivery_type_list.value.findIndex(el => el.key === orderData.value.delivery.delivery_type)
|
|
||||||
!createData.value.delivery.delivery_type && data.delivery.delivery_type && (createData.value.delivery.delivery_type = data.delivery.delivery_type)
|
|
||||||
|
|
||||||
}).catch()
|
|
||||||
}
|
|
||||||
calculate()
|
|
||||||
|
|
||||||
// 改变配送方式
|
|
||||||
watch(
|
|
||||||
() => delivery_type_list.value.length,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if(delivery_type_list.value.length && uni.getStorageSync('distributionType')){
|
|
||||||
delivery_type_list.value.forEach((item: any,index)=>{
|
|
||||||
if(item.name == uni.getStorageSync('distributionType')){
|
|
||||||
activeIndex.value = index;
|
|
||||||
switchDeliveryType(item.key, index)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
uni.removeStorage({ key: 'distributionType' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let orderId = 0
|
|
||||||
/**
|
|
||||||
* 订单创建
|
|
||||||
*/
|
|
||||||
const create = () => {
|
|
||||||
if (!verify() || createLoading.value) return
|
|
||||||
createLoading.value = true
|
|
||||||
|
|
||||||
useSubscribeMessage().request('shop_order_pay,shop_order_delivery')
|
|
||||||
|
|
||||||
orderCreate(createData.value).then(({ data }) => {
|
|
||||||
orderId = data.order_id
|
|
||||||
if (orderData.value.basic.order_money == 0) {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: orderId }, mode: 'redirectTo' })
|
|
||||||
} else {
|
|
||||||
payRef.value?.open(data.trade_type, data.order_id, `/addon/shop/pages/order/detail?order_id=${ data.order_id }`)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
createLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下单校验
|
|
||||||
*/
|
|
||||||
const verify = () => {
|
|
||||||
const data = createData.value
|
|
||||||
let verify = true
|
|
||||||
|
|
||||||
if (orderData.value.basic.has_goods_types.includes('real')) {
|
|
||||||
if (['express', 'local_delivery'].includes(data.delivery.delivery_type) && !orderData.value.delivery.take_address) {
|
|
||||||
uni.showToast({ title: '请选择收货地址', icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.delivery.delivery_type == 'store' && !data.delivery.take_store_id) {
|
|
||||||
uni.showToast({ title: '请选择自提点', icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return verify
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付弹窗关闭
|
|
||||||
*/
|
|
||||||
const payClose = () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: orderId }, mode: 'redirectTo' })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择地址
|
|
||||||
*/
|
|
||||||
const toSelectAddress = () => {
|
|
||||||
let data: any = {};
|
|
||||||
data.delivery = createData.value.delivery.delivery_type;
|
|
||||||
data.type = createData.value.delivery.delivery_type == 'local_delivery' ? 'location_address' : 'address';
|
|
||||||
data.id = orderData.value.delivery.take_address.id;
|
|
||||||
addressRef.value.open(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const couponList = computed(() => {
|
|
||||||
return couponRef.value?.couponList || []
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择优惠券
|
|
||||||
*/
|
|
||||||
const confirmSelectCoupon = (coupon: any) => {
|
|
||||||
createData.value.discount.coupon_id = coupon ? coupon.id : 0
|
|
||||||
calculate()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择自提点
|
|
||||||
*/
|
|
||||||
const confirmSelectStore = (store: any) => {
|
|
||||||
createData.value.delivery.take_store_id = ((store && store.store_id) ? store.store_id: 0)
|
|
||||||
calculate()
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmInvoice = (invoice: object) => {
|
|
||||||
createData.value.invoice = invoice
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmAddress = (data:any) => {
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = data.delivery
|
|
||||||
createData.value.delivery.take_address_id = data.address_id
|
|
||||||
calculate();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.head-tab{
|
|
||||||
.head-tab-item{
|
|
||||||
.tab-image{
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
&:nth-child(1).active{
|
|
||||||
view{
|
|
||||||
padding-right: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:nth-child(2){
|
|
||||||
.tab-image{
|
|
||||||
width: 312rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:nth-child(3).active{
|
|
||||||
view{
|
|
||||||
padding-left: 30rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.active{
|
|
||||||
view{
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tab-img{
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-alert) {
|
|
||||||
padding: 6rpx 16rpx !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
.alert-wrap{
|
|
||||||
display: inline-block !important;
|
|
||||||
:deep(.u-fade-enter-active){
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-ellipsis {
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.line-normal{
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
.bg-color{
|
|
||||||
background: linear-gradient( 94deg, var(--primary-help-color) 0%, var(--primary-color) 69%),var(--primary-color) ;
|
|
||||||
}
|
|
||||||
.payment-bottom{
|
|
||||||
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|
||||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<template>
|
|
||||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10">
|
|
||||||
<view @touchmove.prevent.stop class="popup-common">
|
|
||||||
<view class="title">{{t('selectAddress')}}</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[50vh]">
|
|
||||||
<view v-for="(item,index) in addressList" :key="item.id" class="flex items-center mx-[var(--popup-sidebar-m)] border-1 border-[#eee] border-solid rounded-[var(--rounded-mid)] px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)]" :class="{'mb-[var(--top-m)]': addressList.length-1 != index, 'text-[var(--primary-color)] !border-[var(--primary-color)]': item.id == currAddressId}" @click="selectAddress(index)">
|
|
||||||
<text class="nc-iconfont nc-icon-dingweiV6xx-1 text-[36rpx]"></text>
|
|
||||||
<view class="flex flex-col mx-[20rpx] w-[480rpx]">
|
|
||||||
<view class="flex items-center truncate leading-[1.5]">
|
|
||||||
<text class="mr-[8rpx] text-[30rpx] truncate max-w-[300rpx]">{{item.name}}</text>
|
|
||||||
<text class="text-[30rpx]">{{item.mobile}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="truncate text-[26rpx] leading-[1.5] mt-[12rpx]">{{item.full_address}}</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-xiugaiV6xx text-[32rpx] ml-auto" @click="editAddress(item)"></text>
|
|
||||||
</view>
|
|
||||||
<view v-if="!addressList || addressList && !addressList.length" class="text-[var(--text-color-light6)] text-[28rpx] text-center">{{t('emptyAddress')}}</view>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="addAddress">{{t('addAddress')}}</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { getAddressList } from '@/app/api/member'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect } from '@/utils/common'
|
|
||||||
|
|
||||||
const show = ref(false)
|
|
||||||
const loading = ref(false)
|
|
||||||
const currAddressId = ref('') // 选中的索引
|
|
||||||
const propData: any = ref({})
|
|
||||||
const addressList = ref([])
|
|
||||||
|
|
||||||
const emits = defineEmits(['confirm'])
|
|
||||||
|
|
||||||
const open = (data: Object) => {
|
|
||||||
show.value = true;
|
|
||||||
propData.value = data;
|
|
||||||
currAddressId.value = data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
getAddressList({}).then(({ data }) => {
|
|
||||||
addressList.value = data;
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectAddress = (index: number) => {
|
|
||||||
let data: any = addressList.value[index];
|
|
||||||
if(propData.value.delivery == 'local_delivery' && !data.lat && !data.lng){
|
|
||||||
// 待支付订单-同城配送,选择的地址没有经纬度的情况,会直接跳转到地图界面进行选择
|
|
||||||
// 参数二,表示是否直接跳转到地图界面, 1跳转到地图界面,2表示不跳
|
|
||||||
editAddress(data,1);
|
|
||||||
}else{
|
|
||||||
let obj:any = {}
|
|
||||||
obj.address_id = addressList.value[index].id
|
|
||||||
obj.delivery = propData.value.delivery
|
|
||||||
emits('confirm', obj)
|
|
||||||
}
|
|
||||||
show.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const editAddress = (data: Object, isSelectMap: number = 2)=>{
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'selectAddressCallback',
|
|
||||||
data: {
|
|
||||||
back: '/addon/shop/pages/point/payment',
|
|
||||||
delivery: propData.value.delivery
|
|
||||||
},
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/app/pages/member/address_edit', param: { id: data.id, source: 'shop_order_payment', isSelectMap } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const addAddress = () =>{
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'selectAddressCallback',
|
|
||||||
data: {
|
|
||||||
back: '/addon/shop/pages/point/payment',
|
|
||||||
delivery: propData.value.delivery
|
|
||||||
},
|
|
||||||
success() {
|
|
||||||
redirect({ url: '/app/pages/member/address_edit', param: { source: 'shop_order_payment' } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup class="popup-type" :show="goodsSkuPop" @close="closeFn" mode="bottom">
|
|
||||||
<view class="py-[32rpx] relative" v-if="goodsDetail.detail" @touchmove.prevent.stop>
|
|
||||||
<view class="flex px-[32rpx] mb-[40rpx]">
|
|
||||||
<view class="w-[180rpx] h-[180rpx]">
|
|
||||||
<u--image width="180rpx" height="180rpx" :radius="'var(--goods-rounded-big)'" :src="img(goodsDetail.detail.sku_image)" @click="imgListPreview(goodsDetail.detail.sku_image)" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[180rpx] h-[180rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1 flex-col justify-between ml-[20rpx] py-[10rpx]">
|
|
||||||
<view class="w-[100%]">
|
|
||||||
<view class="text-[var(--price-text-color)] flex items-baseline">
|
|
||||||
<text class="price-font" v-if="goodsDetail.point">
|
|
||||||
<text class="text-[44rpx]">{{goodsDetail.point}}</text>
|
|
||||||
<text class="text-[38rpx]">{{t('point')}}</text>
|
|
||||||
</text>
|
|
||||||
<text class="text-[38rpx]" v-if="goodsDetail.point&&parseFloat(goodsDetail.price)">+</text>
|
|
||||||
<template v-if="goodsDetail.point&&parseFloat(goodsDetail.price)">
|
|
||||||
<text class="text-[44rpx] price-font">{{ parseFloat(goodsDetail.price).toFixed(2) }}</text>
|
|
||||||
<text class="text-[38rpx] price-font">元</text>
|
|
||||||
</template>
|
|
||||||
<template v-if="!goodsDetail.point&&!parseFloat(goodsDetail.price)">
|
|
||||||
<text class="text-[26rpx] price-font">¥</text>
|
|
||||||
<text class="text-[44rpx] price-font">{{ parseFloat(goodsDetail.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[26rpx] mr-[6rpx] price-font">.{{ parseFloat(goodsPrice).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[32rpx] text-[var(--text-color-light6)] mt-[10rpx]">库存{{goodsDetail.detail.stock}}{{ goodsDetail.goods.unit }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[30rpx] text-[var(--text-color-light6)] w-[100%] max-h-[60rpx] multi-hidden" v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length">已选规格:{{goodsDetail.detail.sku_spec_format}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<scroll-view class="h-[500rpx] px-[32rpx] box-border mb-[60rpx]" scroll-y="true">
|
|
||||||
<view :class="{'mt-[20rpx]': 0 != index }" v-for="(item,index) in goodsDetail.goodsSpec" :key="index">
|
|
||||||
<view class="text-[28rpx] leading-[36rpx] mb-[24rpx]">{{item.spec_name}}</view>
|
|
||||||
<view class="flex flex-wrap">
|
|
||||||
<view class="box-border bg-[var(--temp-bg)] text-[24rpx] px-[44rpx] text-center h-[56rpx] flex-center mr-[20rpx] mb-[20rpx] border-1 border-solid rounded-[50rpx] border-[var(--temp-bg)]"
|
|
||||||
:class="{'!border-[var(--primary-color)] text-[var(--primary-color)] !bg-[var(--primary-color-light)]': subItem.selected}"
|
|
||||||
v-for="(subItem,subIndex) in item.values" :key="subIndex"
|
|
||||||
@click="change(subItem, index)">
|
|
||||||
{{subItem.name}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-center mt-[8rpx]">
|
|
||||||
<view class="text-[28rpx]">购买数量</view>
|
|
||||||
<text v-if="goodsDetail.detail.limit_num > 0" class="ml-[20rpx] mr-[auto] text-[24rpx] text-[var(--primary-color)]">(限购{{ goodsDetail.detail.limit_num }}{{ goodsDetail.goods.unit }})</text>
|
|
||||||
<u-number-box :min="1" :max="parseInt(goodsDetail.detail.limit_num)<goodsDetail.stock?parseInt(goodsDetail.detail.limit_num):goodsDetail.stock" integer :step="1" input-width="68rpx" v-model="buyNum" input-height="52rpx">
|
|
||||||
<template #minus>
|
|
||||||
<text class="text-[30rpx] nc-iconfont nc-icon-jianV6xx font-500" :class="{ '!text-[var(--text-color-light9)]': buyNum <= 1 }"></text>
|
|
||||||
</template>
|
|
||||||
<template #input>
|
|
||||||
<input class="text-[#303133] text-[28rpx] mx-[10rpx] w-[80rpx] h-[44rpx] bg-[var(--temp-bg)] leading-[44rpx] text-center rounded-[6rpx]" type="number" @input="goodsSkuInputFn" @blur="goodsSkuBlurFn" v-model="buyNum" />
|
|
||||||
</template>
|
|
||||||
<template #plus>
|
|
||||||
<text class="text-[30rpx] nc-iconfont nc-icon-jiahaoV6xx font-500" :class="{ '!text-[var(--text-color-light9)]': buyNum >= goodsDetail.stock || buyNum ==parseInt(goodsDetail.detail.limit_num)}"></text>
|
|
||||||
</template>
|
|
||||||
</u-number-box>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="px-[20rpx]">
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<button v-if="goodsDetail.detail.stock > 0" hover-class="none" class="!h-[80rpx] primary-btn-bg leading-[80rpx] text-[26rpx] rounded-[50rpx] font-500" type="primary" @click="confirm">确定</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<template v-if="goodsDetail.detail.stock > 0">
|
|
||||||
<button v-if="isBindMobile && userInfo && !userInfo.mobile" hover-class="none" class="!h-[80rpx] primary-btn-bg leading-[80rpx] text-[26rpx] rounded-[50rpx] font-500" type="primary" open-type="getPhoneNumber" @getphonenumber="memberStore.bindMobile">确定</button>
|
|
||||||
<button v-else hover-class="none" class="!h-[80rpx] primary-btn-bg leading-[80rpx] text-[26rpx] rounded-[50rpx] font-500" type="primary" @click="confirm">确定</button>
|
|
||||||
</template>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<button hover-class="none" v-else class="!h-[80rpx] leading-[80rpx] text-[26rpx] text-[#fff] bg-[#ccc] rounded-[50rpx] font-500">已售罄</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
<!-- 强制绑定手机号 -->
|
|
||||||
<bind-mobile ref="bindMobileRef" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, computed } from 'vue';
|
|
||||||
import { img, redirect, getToken } from '@/utils/common'
|
|
||||||
import bindMobile from '@/components/bind-mobile/bind-mobile.vue';
|
|
||||||
import { useLogin } from '@/hooks/useLogin'
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { t } from '@/locale';
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
const props = defineProps(['goodsDetail']);
|
|
||||||
const goodsSkuPop = ref(false);
|
|
||||||
const callback:any = ref(null);
|
|
||||||
const currSpec: any = ref({
|
|
||||||
skuId: "",
|
|
||||||
name: []
|
|
||||||
})
|
|
||||||
const openType = ref("");
|
|
||||||
const buyNum = ref(1)
|
|
||||||
|
|
||||||
// 商品价格
|
|
||||||
const goodsPrice = computed(() => {
|
|
||||||
let price = "0.00";
|
|
||||||
if (Object.keys(goodsDetail.value).length && Object.keys(goodsDetail.value.goods).length && goodsDetail.value.goods.member_discount && getToken() && goodsDetail.value.member_price != goodsDetail.value.price) {
|
|
||||||
// 会员价
|
|
||||||
price = goodsDetail.value.member_price ? goodsDetail.value.member_price : goodsDetail.value.price;
|
|
||||||
} else {
|
|
||||||
price = goodsDetail.value.price
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
})
|
|
||||||
|
|
||||||
const goodsSkuInputFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= 0 ){
|
|
||||||
buyNum.value = 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= Number(goodsDetail.value.detail.limit_num)){
|
|
||||||
buyNum.value = goodsDetail.value.detail.limit_num;
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsSkuBlurFn = ()=>{
|
|
||||||
setTimeout(() => {
|
|
||||||
if(!buyNum.value || buyNum.value <= 0 ){
|
|
||||||
buyNum.value = 1;
|
|
||||||
}
|
|
||||||
if(buyNum.value >= Number(goodsDetail.value.detail.limit_num)){
|
|
||||||
buyNum.value = goodsDetail.value.detail.limit_num;
|
|
||||||
}
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 会员信息
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
const open = (type="",fn = "")=>{
|
|
||||||
openType.value = type;
|
|
||||||
goodsSkuPop.value = true;
|
|
||||||
callback.value = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeFn = ()=>{
|
|
||||||
goodsSkuPop.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsDetail = computed(() => {
|
|
||||||
let data = cloneDeep(props.goodsDetail);
|
|
||||||
|
|
||||||
// 重组数据结构
|
|
||||||
if(Object.keys(data).length){
|
|
||||||
|
|
||||||
if(!Object.keys(currSpec.value.name).length) currSpec.value.name = data.sku_spec_format.split(",");
|
|
||||||
|
|
||||||
data.goodsSpec.forEach((item: any,index: any)=>{
|
|
||||||
let specName = item.spec_values.split(",");
|
|
||||||
item.values = [];
|
|
||||||
specName.forEach((specItem: any, specIndex: any)=>{
|
|
||||||
item.values[specIndex] = {};
|
|
||||||
item.values[specIndex].name = specItem;
|
|
||||||
item.values[specIndex].selected = false;
|
|
||||||
item.values[specIndex].disabled = false;
|
|
||||||
|
|
||||||
// 选中规格
|
|
||||||
currSpec.value.name.forEach((currSpecItem, currSpecIndex)=>{
|
|
||||||
if(currSpecIndex == index && currSpecItem == specItem){
|
|
||||||
item.values[specIndex].selected = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
getSkuId();
|
|
||||||
|
|
||||||
// 当前详情内容
|
|
||||||
if(data.skuList && Object.keys(data.skuList).length){
|
|
||||||
data.skuList.forEach((idItem: any, idIndex: any)=>{
|
|
||||||
if(idItem.sku_id == currSpec.value.skuId){
|
|
||||||
data.detail = idItem;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
})
|
|
||||||
|
|
||||||
const change = (data: any, index: any)=>{
|
|
||||||
currSpec.value.name[index] = data.name;
|
|
||||||
buyNum.value = 1
|
|
||||||
getSkuId();
|
|
||||||
}
|
|
||||||
|
|
||||||
const emits = defineEmits(['change'])
|
|
||||||
const getSkuId = ()=>{
|
|
||||||
props.goodsDetail.skuList.forEach((skuItem: any, skuIndex: any)=>{
|
|
||||||
if(skuItem.sku_spec_format == currSpec.value.name.toString()){
|
|
||||||
currSpec.value.skuId = skuItem.sku_id
|
|
||||||
emits('change',skuItem.sku_id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//强制绑定手机号
|
|
||||||
const bindMobileRef: any = ref(null)
|
|
||||||
const isBindMobile = ref(uni.getStorageSync('isbindmobile'))
|
|
||||||
|
|
||||||
const confirm = ()=> {
|
|
||||||
// 检测是否登录
|
|
||||||
if (!userInfo.value) {
|
|
||||||
useLogin().setLoginBack({url: '/addon/shop/pages/point/detail', param: {id: goodsDetail.value.exchange_id}})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
// 绑定手机号
|
|
||||||
if(uni.getStorageSync('isbindmobile')){
|
|
||||||
bindMobileRef.value.open()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 立即购买
|
|
||||||
var data = {
|
|
||||||
sku_id: goodsDetail.value.sku_id,
|
|
||||||
num: buyNum.value
|
|
||||||
};
|
|
||||||
|
|
||||||
uni.setStorage({
|
|
||||||
key: 'orderCreateData',
|
|
||||||
data: {
|
|
||||||
sku_data: [
|
|
||||||
data
|
|
||||||
]
|
|
||||||
},
|
|
||||||
success: () => {
|
|
||||||
redirect({url: '/addon/shop/pages/point/payment'})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
closeFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item: any) => {
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.popup-type {
|
|
||||||
:deep(.u-popup__content) {
|
|
||||||
border-top-left-radius: 16rpx;
|
|
||||||
border-top-right-radius: 16rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 防止覆盖住图片放大
|
|
||||||
.u-popup :deep(.u-transition){
|
|
||||||
z-index: 999 !important;
|
|
||||||
}
|
|
||||||
::v-deep .u-number-box .u-number-box__slot{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,630 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<scroll-view scroll-y="true" class="h-[100vh] w-full">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh] relative" v-if="Object.keys(goodsDetail).length">
|
|
||||||
<!-- 自定义头部 -->
|
|
||||||
<view class="flex items-center fixed left-0 right-0 z-10 bg-transparent detail-head" :class="{'!bg-[#fff]' :detailHeadBgChange}" :style="navbarInnerStyle">
|
|
||||||
<text class="nc-iconfont nc-icon-zuoV6xx" :style="navbarInnerArrowStyle" @click="backToPrevious()"></text>
|
|
||||||
<view class="ml-auto !pt-[12rpx] !pb-[8rpx] p-[10rpx] bg-[rgba(255,255,255,.4)] rounded-full border-[2rpx] border-solid border-transparent box-border nc-iconfont nc-icon-fenxiangV6xx font-bold text-[#303133] text-[36rpx]" :class="{'border-[#d8d8d8]': detailHeadBgChange}" @click="openShareFn"></view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="swiper-box">
|
|
||||||
<u-swiper :list="goodsDetail.goods.goods_image" :indicator="goodsDetail.goods.goods_image.length" :indicatorStyle="{'bottom': '68rpx',}" :autoplay="true" height="100vw" @click="swiperClick"></u-swiper>
|
|
||||||
</view>
|
|
||||||
<view class="rounded-t-[40rpx] -mt-[40rpx] relative flex items-center justify-between !bg-cover box-border pb-[26rpx] h-[136rpx] px-[30rpx]" :style="{ background: 'url(' + img('addon/shop/detail/discount_price_bg.png') + ') no-repeat'}">
|
|
||||||
<view class="flex items-baseline text-[#fff]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="inline-block price-font" v-if="goodsDetail.point">
|
|
||||||
<text class="text-[44rpx]">{{goodsDetail.point}}</text>
|
|
||||||
<text class="text-[38rpx]">{{t('point')}}</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-[38rpx]" v-if="goodsDetail.point&&parseFloat(goodsDetail.price)">+</text>
|
|
||||||
<view class="inline-block price-font" v-if="parseFloat(goodsDetail.price)">
|
|
||||||
<text class="text-[44rpx]">{{parseFloat(goodsDetail.price).toFixed(2)}}</text>
|
|
||||||
<text class="text-[38rpx]">{{t('priceUnit')}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="bg-[var(--page-bg-color)] overflow-hidden rounded-[40rpx] -mt-[28rpx] relative">
|
|
||||||
<view class="datail-title relative px-[30rpx] pt-[40rpx]">
|
|
||||||
<view class="text-[#333] font-medium text-[30rpx] multi-hidden leading-[40rpx]">
|
|
||||||
<view class="brand-tag middle" v-if="goodsDetail.goods.goods_brand">
|
|
||||||
{{goodsDetail.goods.goods_brand.brand_name}}
|
|
||||||
</view>
|
|
||||||
{{ goodsDetail.goods.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-start mt-[24rpx] ">
|
|
||||||
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)]" v-if="goodsDetail.market_price && parseFloat(goodsDetail.market_price)">
|
|
||||||
<text class="whitespace-nowrap mr-[4rpx]">划线价:</text>
|
|
||||||
<text class="line-through">¥{{ goodsDetail.market_price }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)]" v-if="goodsDetail.stock && parseFloat(goodsDetail.stock)">
|
|
||||||
<text class="whitespace-nowrap mr-[4rpx]">库存:</text>
|
|
||||||
<text class="">{{ goodsDetail.stock }}</text>
|
|
||||||
<text class="">{{ goodsDetail.goods.unit }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)] flex items-baseline">
|
|
||||||
<text class="whitespace-nowrap mr-[4rpx]">销量:</text>
|
|
||||||
<text class="mx-[2rpx]">{{ goodsDetail.goods.sale_num }}</text>
|
|
||||||
<text class="">{{ goodsDetail.goods.unit }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-wrap mt-[16rpx]" v-if="goodsDetail.label_info && goodsDetail.label_info.length">
|
|
||||||
<block v-for="item in goodsDetail.label_info" :key="item.label_id">
|
|
||||||
<image class="img-tag middle" v-if="item.style_type == 'icon' && item.icon" :src="img(item.icon)" mode="heightFix" @error="diyGoods.error(item,'icon')"></image>
|
|
||||||
<view class="base-tag middle" v-else-if="item.style_type == 'diy' || !item.icon" :style="diyGoods.baseTagStyle(item)">
|
|
||||||
{{item.label_name}}
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[24rpx] sidebar-margin card-template" v-if="isGoodsPropertyTemp">
|
|
||||||
<view @click="servicesDataShow = !servicesDataShow" v-if="goodsDetail.service && goodsDetail.service.length" class="card-template-item">
|
|
||||||
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0">服务</text>
|
|
||||||
<view class="text-[#343434] text-[26rpx] leading-[30rpx] font-400 truncate ml-auto">
|
|
||||||
{{ goodsDetail.service[0].service_name }}
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view @click="buyFn" v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length" class="card-template-item">
|
|
||||||
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0 mr-[20rpx]">已选</text>
|
|
||||||
<view class="ml-auto text-right truncate flex-1 text-[#343434] text-[26rpx] leading-[30rpx] font-400">
|
|
||||||
{{ goodsDetail.sku_spec_format }}
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item" @click="distributionDataOpen" v-if="goodsDetail.goods.goods_type == 'real' && goodsDetail.delivery_type_list && goodsDetail.delivery_type_list.length" >
|
|
||||||
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0">配送</text>
|
|
||||||
<view class="ml-auto flex items-center text-[#343434] text-[26rpx] leading-[30rpx] font-400">
|
|
||||||
{{ goodsDetail.delivery_type_list[selectDeliveryType].name }}
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="mt-[var(--top-m)] sidebar-margin card-template">
|
|
||||||
<view class="flex items-center justify-between min-h-[40rpx]" :class="{'mb-[30rpx]': evaluate && evaluate.list && evaluate.list.length}">
|
|
||||||
<text class="title !mb-[0]">宝贝评价({{ evaluate.count }})</text>
|
|
||||||
<view v-if="evaluate.count" class="h-[40rpx] flex items-center" @click="toLink(goodsDetail.goods_id)">
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)]">查看全部</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<text v-if="!evaluate.count" class="text-[24rpx] text-[var(--text-color-light6)]">暂无评价</text>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<view :class="{'pb-[34rpx]': index != (evaluate.list.length-1)}" v-for="(item, index) in evaluate.list" :key="index">
|
|
||||||
<view class="flex items-center w-full">
|
|
||||||
<u-avatar :default-url="img('static/resource/images/default_headimg.png')" :src="img(item.member_head)" :size="'50rpx'" leftIcon="none" />
|
|
||||||
<text class="ml-[10rpx] text-[28rpx] text-[#333]">{{ item.member_name }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between w-full mt-[16rpx]">
|
|
||||||
<view class="flex-1 w-[540rpx] text-[26rpx] text-[#333] max-h-[72rpx] leading-[36rpx] multi-hidden mr-[50rpx]">{{ item.content }}</view>
|
|
||||||
<view class="w-[80rpx] shrink-0">
|
|
||||||
<u--image v-if="item.image_mid && item.image_mid.length" width="80rpx" height="80rpx" radius="16rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
|
|
||||||
<template #error>
|
|
||||||
<u-icon name="photo" color="#999" size="50"></u-icon>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="my-[var(--top-m)] goods-sku sidebar-margin card-template" v-if="goodsDetail.goods && goodsDetail.goods.attr_format && Object.keys(goodsDetail.goods.attr_format).length">
|
|
||||||
<view class="title mb-[30rpx]">商品属性</view>
|
|
||||||
<view>
|
|
||||||
<block v-for="(item,index) in goodsDetail.goods.attr_format" :key="index">
|
|
||||||
<view v-if="index < 4 || isAttrFormatShow" class="card-template-item">
|
|
||||||
<view class="text-[26rpx] leading-[30rpx] w-[160rpx] font-400 shrink-0 text-[var(--text-color-light9)]">{{item.attr_value_name}}</view>
|
|
||||||
<view class="text-[#333] box-border value-wid text-[26rpx] leading-[30rpx] font-400 truncate pl-[20rpx]">{{Array.isArray(item.attr_child_value_name) ? item.attr_child_value_name.join(',') : item.attr_child_value_name }}</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<view v-if="goodsDetail.goods.attr_format.length > 4" class="flex-center" @click="isAttrFormatShow = !isAttrFormatShow">
|
|
||||||
<text class="text-[24rpx] mr-[10rpx]">{{isAttrFormatShow ? '展开' : '收起'}}</text>
|
|
||||||
<text class="nc-iconfont !text-[22rpx]" :class="{'nc-icon-xiaV6xx': isAttrFormatShow, 'nc-icon-shangV6xx-1': !isAttrFormatShow}"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin card-template px-[var(--pad-sidebar-m)]">
|
|
||||||
<view class="title">商品详情</view>
|
|
||||||
<view class="u-content">
|
|
||||||
<u-parse :content="goodsDetail.goods.goods_desc" :tagStyle="{img: 'vertical-align: top;',p:'overflow: hidden;word-break:break-word;' }"></u-parse>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="tab-bar-placeholder"></view>
|
|
||||||
<view class="border-[0] border-t-[2rpx] border-solid border-[#f5f5f5] w-[100%] flex justify-between pl-[32rpx] pr-[4rpx] bg-[#fff] box-border fixed left-0 bottom-0 tab-bar z-1 items-center">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="flex flex-col justify-center items-center mr-[38rpx]" @click="redirect({ url: '/addon/shop/pages/index', mode: 'reLaunch' })">
|
|
||||||
<view class="nc-iconfont nc-icon-shouyeV6xx text-[36rpx]"></view>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">首页</text>
|
|
||||||
</view>
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<view class="flex flex-col justify-center items-center mr-[38rpx]" @click="openShareFn">
|
|
||||||
<view class="nc-iconfont nc-icon-fenxiangV6xx text-[36rpx]"></view>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">分享</text>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view>
|
|
||||||
<nc-contact
|
|
||||||
:send-message-title="sendMessageTitle"
|
|
||||||
:send-message-path="sendMessagePath"
|
|
||||||
:send-message-img="sendMessageImg">
|
|
||||||
<view class="flex flex-col justify-center items-center mr-[38rpx]">
|
|
||||||
<text class="nc-iconfont nc-icon-kefuV6xx-1 text-[36rpx]"></text>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">客服</text>
|
|
||||||
</view>
|
|
||||||
</nc-contact>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1" v-if="goodsDetail.goods.status == 1">
|
|
||||||
<button
|
|
||||||
v-if="isShowSingleSku"
|
|
||||||
class="primary-btn-bg flex-1 !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !m-0 !mr-[16rpx] leading-[70rpx] rounded-full remove-border"
|
|
||||||
@click="buyFn('buy_now')">立即兑换</button>
|
|
||||||
<button v-else
|
|
||||||
class="flex-1 !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !bg-[#ccc] !m-0 !mr-[16rpx] leading-[70rpx] rounded-full remove-border"
|
|
||||||
>已售罄</button>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-1" v-else>
|
|
||||||
<button class="w-[100%] !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !bg-[#ccc] !m-0 leading-[70rpx] rounded-full remove-border">该商品已下架</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 服务 -->
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup class="popup-type" :show="servicesDataShow" @close="servicesDataShow = false">
|
|
||||||
<view class="popup-common min-h-[480rpx]" @touchmove.prevent.stop>
|
|
||||||
<view class="title">商品服务</view>
|
|
||||||
<scroll-view class="h-[520rpx]" scroll-y="true">
|
|
||||||
<view class="pl-[22rpx] pb-[28rpx] pr-[37rpx]">
|
|
||||||
<view class="flex mb-[28rpx]" v-for="(item, index) in goodsDetail.service">
|
|
||||||
<image class="mt-[4rpx] w-[32rpx] h-[32rpx] mr-[14rpx]" :src="img(item.image || 'addon/shop/icon_service.png')" mode="aspectFit" />
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx] leading-[36rpx] text-[#333] mb-[8rpx]">{{ item.service_name }}</view>
|
|
||||||
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)]">{{ item.desc }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
<!-- 配送 -->
|
|
||||||
<view @touchmove.prevent.stop>
|
|
||||||
<u-popup class="popup-type" :show="distributionDataShow" @close="distributionDataShow = false">
|
|
||||||
<view class="min-h-[360rpx] popup-common" @touchmove.prevent.stop>
|
|
||||||
<view class="title">配送方式</view>
|
|
||||||
<scroll-view class="h-[520rpx]" scroll-y="true">
|
|
||||||
<view class="px-[var(--popup-sidebar-m)]">
|
|
||||||
<view class="flex mb-[40rpx]" v-for="(item, index) in goodsDetail.delivery_type_list" @click="distributionListFn(item,index)">
|
|
||||||
<image class="mt-[4rpx] w-[32rpx] h-[32rpx] mr-[14rpx]" :src="img('addon/shop/icon_service.png')" mode="aspectFit" />
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx] leading-[36rpx] text-[#333] mb-[8rpx]">{{ item.name }}</view>
|
|
||||||
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)]">{{ item.desc }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</view>
|
|
||||||
<goods-sku ref="goodsSkuRef" :goods-detail="goodsDetail" @change="specSelectFn"></goods-sku>
|
|
||||||
<share-poster ref="sharePosterRef" posterType="shop_point_goods" :posterParam="posterParam" :copyUrlParam="copyUrlParam" />
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, getCurrentInstance, nextTick } from 'vue';
|
|
||||||
import { onLoad, onShow,onUnload,onPageScroll } from '@dcloudio/uni-app'
|
|
||||||
import { img, redirect,handleOnloadParams, deepClone, goback } from '@/utils/common';
|
|
||||||
import { t } from '@/locale';
|
|
||||||
import { getEvaluateList } from '@/addon/shop/api/goods';
|
|
||||||
import { getExchangeGoodsDetail } from '@/addon/shop/api/point';
|
|
||||||
import goodsSku from '@/addon/shop/pages/point/components/goods-sku.vue';
|
|
||||||
import useMemberStore from '@/stores/member'
|
|
||||||
import { useShare }from '@/hooks/useShare'
|
|
||||||
import sharePoster from '@/components/share-poster/share-poster.vue'
|
|
||||||
import {useGoods} from '@/addon/shop/hooks/useGoods'
|
|
||||||
|
|
||||||
const diyGoods = useGoods();
|
|
||||||
// 分享
|
|
||||||
const{setShare} = useShare()
|
|
||||||
|
|
||||||
// 会员信息
|
|
||||||
const memberStore = useMemberStore()
|
|
||||||
const userInfo = computed(() => memberStore.info)
|
|
||||||
|
|
||||||
const sendMessageTitle = ref('')
|
|
||||||
const sendMessagePath = ref('')
|
|
||||||
const sendMessageImg = ref('')
|
|
||||||
|
|
||||||
const goodsSkuRef: any = ref(null);
|
|
||||||
const goodsDetail: any = ref({});
|
|
||||||
|
|
||||||
const isAttrFormatShow = ref(false); //控制属性是否展开
|
|
||||||
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const servicesDataShow = ref<boolean>(false)
|
|
||||||
const distributionDataShow = ref<boolean>(false) //配送
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 处理小程序场景值参数
|
|
||||||
option = handleOnloadParams(option);
|
|
||||||
// #endif
|
|
||||||
//
|
|
||||||
getExchangeGoodsDetail(option.id || '',).then((res: any) => {
|
|
||||||
if (JSON.stringify(res.data) === '[]') {
|
|
||||||
let goBackParameter = {
|
|
||||||
url:'/addon/shop/pages/index',
|
|
||||||
title: '找不到该商品',
|
|
||||||
mode: 'reLaunch'
|
|
||||||
};
|
|
||||||
goback(goBackParameter)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
goodsDetail.value = deepClone(res.data);
|
|
||||||
|
|
||||||
goodsDetail.value.delivery_type_list = goodsDetail.value.goods.delivery_type_list ? Object.values(goodsDetail.value.goods.delivery_type_list) : [];
|
|
||||||
goodsDetail.value.goods.goods_image = goodsDetail.value.goods.goods_image_thumb_big;
|
|
||||||
goodsDetail.value.goods.goods_image.forEach((item: any, index: any) => {
|
|
||||||
goodsDetail.value.goods.goods_image[index] = img(item);
|
|
||||||
})
|
|
||||||
|
|
||||||
let data: any = deepClone(res.data);
|
|
||||||
goodsDetail.value.goods.attr_format = []
|
|
||||||
if (data.goods && data.goods.attr_format) {
|
|
||||||
let attrFormatArr: any = deepClone(JSON.parse(data.goods.attr_format));
|
|
||||||
attrFormatArr.forEach((item: any, index: any) => {
|
|
||||||
if ((item.attr_child_value_name && !(item.attr_child_value_name instanceof Array)) || ((item.attr_child_value_name instanceof Array) && item.attr_child_value_name.length)) {
|
|
||||||
goodsDetail.value.goods.attr_format.push(item);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessageTitle.value = goodsDetail.value.goods.goods_name
|
|
||||||
sendMessagePath.value = '/addon/shop/pages/point/detail?sku_id=' + goodsDetail.value.sku_id;
|
|
||||||
sendMessageImg.value = img(goodsDetail.value.goods.goods_cover_thumb_mid)
|
|
||||||
|
|
||||||
// 分享 - start
|
|
||||||
let share = {
|
|
||||||
title: goodsDetail.value.goods.goods_name,
|
|
||||||
desc: goodsDetail.value.goods.sub_title,
|
|
||||||
url: goodsDetail.value.goods.goods_cover_thumb_mid
|
|
||||||
}
|
|
||||||
uni.setNavigationBarTitle({
|
|
||||||
title: goodsDetail.value.goods.goods_name
|
|
||||||
})
|
|
||||||
setShare({
|
|
||||||
wechat: {
|
|
||||||
...share
|
|
||||||
},
|
|
||||||
weapp: {
|
|
||||||
...share
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 分享 - end
|
|
||||||
|
|
||||||
// 获取评价
|
|
||||||
getEvaluateListFn();
|
|
||||||
|
|
||||||
copyUrlFn();
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
query.select('.swiper-box').boundingClientRect((data: any) => {
|
|
||||||
swiperHeight = data ? data.height : 0;
|
|
||||||
}).exec();
|
|
||||||
query.select('.detail-head').boundingClientRect((data: any) => {
|
|
||||||
if (data) {
|
|
||||||
detailHead = data.height ? data.height : 0;
|
|
||||||
}
|
|
||||||
}).exec();
|
|
||||||
}, 400)
|
|
||||||
// #ifdef MP
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
onShow(() => {
|
|
||||||
// 删除配送方式
|
|
||||||
uni.removeStorageSync('distributionType');
|
|
||||||
})
|
|
||||||
|
|
||||||
const specSelectFn = (id: any) => {
|
|
||||||
goodsDetail.value.skuList.forEach((item: any, index: any) => {
|
|
||||||
if (item.sku_id == id) {
|
|
||||||
Object.assign(goodsDetail.value, item);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断单规格库存是否为0
|
|
||||||
const isShowSingleSku = computed(() => {
|
|
||||||
let isSingleSpec = false // 是否为单规格,true:多规格,false:单规格
|
|
||||||
goodsDetail.value.skuList.forEach((item: any,index: any)=>{
|
|
||||||
if(item.sku_spec_format){
|
|
||||||
isSingleSpec = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 单规格,库存为0,显示已售罄
|
|
||||||
if(!isSingleSpec && goodsDetail.value.stock <= 0){
|
|
||||||
return false;
|
|
||||||
}else if(!isSingleSpec && goodsDetail.value.stock > 0){
|
|
||||||
// 单规格,库存大于0,可以购买
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 判断商品属性模块是否展示
|
|
||||||
const isGoodsPropertyTemp = computed(() => {
|
|
||||||
let bool = false;
|
|
||||||
if(goodsDetail.value.service && goodsDetail.value.service.length ||
|
|
||||||
goodsDetail.value.goodsSpec && goodsDetail.value.goodsSpec.length ||
|
|
||||||
goodsDetail.value.goods.goods_type == 'real'&&goodsDetail.value.delivery_type_list&&goodsDetail.value.delivery_type_list.length){
|
|
||||||
bool = true;
|
|
||||||
}
|
|
||||||
return bool;
|
|
||||||
})
|
|
||||||
|
|
||||||
const buyFn = (type: any) => {
|
|
||||||
goodsSkuRef.value.open(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取评价
|
|
||||||
const evaluate = ref({
|
|
||||||
count : 0
|
|
||||||
})
|
|
||||||
|
|
||||||
const getEvaluateListFn = () => {
|
|
||||||
getEvaluateList(goodsDetail.value.goods_id).then((res: any) => {
|
|
||||||
evaluate.value = res.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//进入评论
|
|
||||||
const toLink = () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/list', param: { goods_id: goodsDetail.value.goods_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
//预览图片
|
|
||||||
const imgListPreview = (item:any,index:any) => {
|
|
||||||
if(Array.isArray(item)){
|
|
||||||
var urlList =item;
|
|
||||||
if (!item.length) return false
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
current:index,
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
if (item === '') return false
|
|
||||||
var urlList = []
|
|
||||||
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
|
|
||||||
uni.previewImage({
|
|
||||||
indicator: "number",
|
|
||||||
loop: true,
|
|
||||||
urls: urlList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// 返回上一页
|
|
||||||
const backToPrevious=()=> {
|
|
||||||
if(getCurrentPages().length > 1){
|
|
||||||
uni.navigateBack({
|
|
||||||
delta: 1
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/index',
|
|
||||||
mode: 'reLaunch'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/************ 选择配送方式-start ****************/
|
|
||||||
const selectDeliveryType = ref(0);
|
|
||||||
const distributionDataOpen = (()=>{
|
|
||||||
distributionDataShow.value = true;
|
|
||||||
});
|
|
||||||
const distributionListFn = ((data: any,index: any)=>{
|
|
||||||
selectDeliveryType.value = index;
|
|
||||||
distributionDataShow.value = false;
|
|
||||||
uni.setStorageSync('distributionType', data.name);
|
|
||||||
});
|
|
||||||
/************ 选择配送方式-end ****************/
|
|
||||||
|
|
||||||
|
|
||||||
/************ 自定义头部-start ****************/
|
|
||||||
// 获取系统状态栏的高度
|
|
||||||
let systemInfo = uni.getSystemInfoSync();
|
|
||||||
let platform = systemInfo.platform;
|
|
||||||
let menuButtonInfo: any = {};
|
|
||||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
|
||||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
|
||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 导航栏内部盒子的样式
|
|
||||||
const navbarInnerStyle = computed(() => {
|
|
||||||
let style = '';
|
|
||||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
|
||||||
// #ifdef MP
|
|
||||||
let rightButtonWidth = menuButtonInfo.width ? menuButtonInfo.width * 2 + 'rpx' : '70rpx';
|
|
||||||
style += 'height:' + menuButtonInfo.height + 'px;';
|
|
||||||
style += 'padding-right:calc(' + rightButtonWidth + ' + 30rpx);';
|
|
||||||
style += 'padding-left:calc(' + rightButtonWidth + ' + 30rpx);';
|
|
||||||
style += 'padding-top:' + menuButtonInfo.top + 'px;';
|
|
||||||
style += 'padding-bottom: 8px;';
|
|
||||||
|
|
||||||
style += 'font-size: 32rpx;';
|
|
||||||
if (platform === 'ios') {
|
|
||||||
// 苹果(iOS)设备
|
|
||||||
style += 'font-weight: 500;';
|
|
||||||
} else if (platform === 'android') {
|
|
||||||
// 安卓(Android)设备
|
|
||||||
style += 'font-size: 36rpx;';
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
style += 'height: 100rpx;';
|
|
||||||
style += 'padding-right: 30rpx;';
|
|
||||||
style += 'padding-left: 30rpx;';
|
|
||||||
|
|
||||||
style += 'font-size: 32rpx;';
|
|
||||||
if (platform === 'ios') {
|
|
||||||
// 苹果(iOS)设备
|
|
||||||
style += 'font-weight: 500;';
|
|
||||||
} else if (platform === 'android') {
|
|
||||||
// 安卓(Android)设备
|
|
||||||
style += 'font-size: 36rpx;';
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 导航栏内部盒子的样式
|
|
||||||
const navbarInnerArrowStyle = computed(() => {
|
|
||||||
let style = '';
|
|
||||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
|
||||||
// #ifdef MP
|
|
||||||
style += "padding-left: 10rpx;"
|
|
||||||
style += "padding-right: 10rpx;"
|
|
||||||
style += 'position: absolute;';
|
|
||||||
style += 'left:calc( 100vw - ' + menuButtonInfo.right + 'px);';
|
|
||||||
style += 'font-size: 26px;';
|
|
||||||
// style += 'font-weight: bold;';
|
|
||||||
if (platform === 'ios') {
|
|
||||||
// 苹果(iOS)设备
|
|
||||||
style += 'font-weight: 700;';
|
|
||||||
} else if (platform === 'android') {
|
|
||||||
// 安卓(Android)设备
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
style += 'font-size: 26px;';
|
|
||||||
// #endif
|
|
||||||
return style;
|
|
||||||
})
|
|
||||||
|
|
||||||
// 头部滚动
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
let swiperHeight = 0
|
|
||||||
let detailHead = 0
|
|
||||||
|
|
||||||
const detailHeadBgChange = ref(false)
|
|
||||||
onPageScroll((e)=>{
|
|
||||||
let height = swiperHeight - detailHead - 20;
|
|
||||||
detailHeadBgChange.value = false;
|
|
||||||
if(e.scrollTop >= height){
|
|
||||||
detailHeadBgChange.value = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
/************ 自定义头部-end ****************/
|
|
||||||
|
|
||||||
const swiperClick = (index: any)=>{
|
|
||||||
if(typeof index == 'number') imgListPreview(goodsDetail.value.goods.goods_image,index)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************* 分享海报-start **************/
|
|
||||||
const sharePosterRef: any = ref(null);
|
|
||||||
const copyUrlParam = ref('');
|
|
||||||
let posterParam: any = {};
|
|
||||||
|
|
||||||
// 分享海报链接
|
|
||||||
const copyUrlFn = ()=>{
|
|
||||||
copyUrlParam.value = '?id='+goodsDetail.value.exchange_id;
|
|
||||||
if (userInfo.value && userInfo.value.member_id) copyUrlParam.value += '&mid=' + userInfo.value.member_id;
|
|
||||||
}
|
|
||||||
const openShareFn = ()=>{
|
|
||||||
posterParam.id = goodsDetail.value.exchange_id;
|
|
||||||
if (userInfo.value && userInfo.value.member_id) {
|
|
||||||
posterParam.member_id = userInfo.value.member_id;
|
|
||||||
}
|
|
||||||
sharePosterRef.value.openShare()
|
|
||||||
}
|
|
||||||
/************* 分享海报-end **************/
|
|
||||||
|
|
||||||
// 关闭预览图片
|
|
||||||
onUnload(()=>{
|
|
||||||
// #ifdef H5 || APP
|
|
||||||
uni.closePreviewImage()
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/addon/shop/styles/common.scss';
|
|
||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(.u-cell-group__wrapper) {
|
|
||||||
.u-cell__body {
|
|
||||||
padding: 23rpx 32rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-type {
|
|
||||||
:deep(.u-popup__content) {
|
|
||||||
border-top-left-radius: 16rpx;
|
|
||||||
border-top-right-radius: 16rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-bar-placeholder {
|
|
||||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 100rpx);
|
|
||||||
padding-bottom: calc(env(safe-area-inset-bottom) + 100rpx);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-bar {
|
|
||||||
padding-top: 16rpx;
|
|
||||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 16rpx);
|
|
||||||
padding-bottom: calc(env(safe-area-inset-bottom) + 16rpx);
|
|
||||||
}
|
|
||||||
:deep(.u-count-down) .u-count-down__text{
|
|
||||||
color: #fff;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
:deep(.u-swiper-indicator__wrapper--line__bar){
|
|
||||||
height: 5rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-swiper-indicator__wrapper--line){
|
|
||||||
height: 5rpx !important;
|
|
||||||
}
|
|
||||||
.datail-title{
|
|
||||||
background: linear-gradient(#fff 70%, #F6F6F6);
|
|
||||||
}
|
|
||||||
.goods-sku .value-wid{
|
|
||||||
width: calc(100% - 160rpx);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
|
|
||||||
<loading-page :loading="diy.getLoading()"></loading-page>
|
|
||||||
|
|
||||||
<view v-show="!diy.getLoading()">
|
|
||||||
|
|
||||||
<!-- 自定义模板渲染 -->
|
|
||||||
<view class="diy-template-wrap bg-index" v-if="diy.data.pageMode != 'fixed'" :style="diy.pageStyle()">
|
|
||||||
|
|
||||||
<diy-group ref="diyGroupRef" :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 固定模板渲染 -->
|
|
||||||
<view class="fixed-template-wrap" v-if="diy.data.pageMode == 'fixed'">
|
|
||||||
|
|
||||||
<fixed-group :data="diy.data" :pullDownRefreshCount="diy.pullDownRefreshCount" />
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import {ref,nextTick} from 'vue';
|
|
||||||
import {useDiy} from '@/hooks/useDiy'
|
|
||||||
import diyGroup from '@/addon/components/diy/group/index.vue'
|
|
||||||
import fixedGroup from '@/addon/components/fixed/group/index.vue'
|
|
||||||
|
|
||||||
const diy = useDiy({
|
|
||||||
name: 'DIY_SHOP_POINT_INDEX'
|
|
||||||
})
|
|
||||||
|
|
||||||
const diyGroupRef = ref(null)
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
// 监听页面加载
|
|
||||||
diy.onLoad();
|
|
||||||
|
|
||||||
// 监听页面显示
|
|
||||||
diy.onShow((data: any) => {
|
|
||||||
diyGroupRef.value?.refresh();
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听页面隐藏
|
|
||||||
diy.onHide();
|
|
||||||
|
|
||||||
// 监听页面卸载
|
|
||||||
diy.onUnload();
|
|
||||||
|
|
||||||
// 监听下拉刷新事件
|
|
||||||
diy.onPullDownRefresh()
|
|
||||||
|
|
||||||
// 监听滚动事件
|
|
||||||
diy.onPageScroll()
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '@/styles/diy.scss';
|
|
||||||
</style>
|
|
||||||
<style lang="scss">
|
|
||||||
.diy-template-wrap {
|
|
||||||
/* #ifdef MP */
|
|
||||||
.child-diy-template-wrap {
|
|
||||||
::v-deep .diy-group {
|
|
||||||
> .draggable-element.top-fixed-diy {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh]" :style="themeColor()">
|
|
||||||
<view class="fixed left-0 right-0 top-0 product-warp bg-[#fff]">
|
|
||||||
|
|
||||||
<view class="py-[14rpx] flex items-center justify-between px-[20rpx]">
|
|
||||||
<view class="flex-1 search-input">
|
|
||||||
<text @click.stop="searchTypeFn('all')" class="nc-iconfont nc-icon-sousuo-duanV6xx1 btn"></text>
|
|
||||||
<input class="input" maxlength="50" type="text" v-model="goods_name" placeholder="请搜索您想要的商品" placeholderClass="text-[var(--text-color-light9)] text-[24rpx]" confirm-type="search" @confirm="searchTypeFn('all')">
|
|
||||||
<text v-if="goods_name" class="nc-iconfont nc-icon-cuohaoV6xx1 clear" @click="goods_name=''"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="h-[88rpx] px-[30rpx]">
|
|
||||||
<view class=" flex items-center justify-between text-[26rpx] text-[var(--text-color-light6)] h-[88rpx]">
|
|
||||||
<text class="" :class="{ '!text-[var(--primary-color)] font-500': searchType == 'total_order_num' }" @click="searchTypeFn('total_order_num')">综合排序</text>
|
|
||||||
<view class="flex items-center" @click="searchTypeFn('total_exchange_num')">
|
|
||||||
<text class="mr-[4rpx]" :class="{ '!text-[var(--primary-color)] font-500': searchType == 'total_exchange_num' }">销量</text>
|
|
||||||
<text v-if="sale_num == 'asc'" class="text-[16rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangshangV6xx1"
|
|
||||||
:class="{ '!text-[var(--primary-color)]': searchType == 'total_exchange_num' }"
|
|
||||||
></text>
|
|
||||||
<text v-else class="text-[16rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangxiaV6xx1"
|
|
||||||
:class="{ '!text-[var(--primary-color)]': searchType == 'total_exchange_num' }"></text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center" @click="searchTypeFn('price')">
|
|
||||||
<text class="mr-[4rpx]" :class="{'!text-[var(--primary-color)] font-500': searchType == 'price' }">价格</text>
|
|
||||||
<text v-if="price == 'asc'" class="text-[16rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangshangV6xx1"
|
|
||||||
:class="{'!text-[var(--primary-color)]': searchType == 'price' }"></text>
|
|
||||||
<text v-else class="text-[16rpx] text-[var(--text-color-light6)] nc-iconfont nc-icon-a-xiangxiaV6xx1"
|
|
||||||
:class="{'!text-[var(--primary-color)]': searchType == 'price' }"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<mescroll-body ref="mescrollRef" top="176rpx" bottom="60px" @init="mescrollInit" :down="{ use: false }" @up="getAllAppListFn">
|
|
||||||
<view v-if="goodsList.length" class="sidebar-margin flex justify-between flex-wrap">
|
|
||||||
<template v-for="(item, index) in goodsList">
|
|
||||||
<view class="goods-item-style-two flex flex-col bg-[#fff] box-border rounded-[var(--rounded-mid)] overflow-hidden mt-[var(--top-m)]" @click="toDetail(item.id)">
|
|
||||||
<!-- <u--image width="100%" height="350rpx" :src="img(item.goods_cover_thumb_mid ? item.goods_cover_thumb_mid : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[100%] h-[350rpx]" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image> -->
|
|
||||||
<image v-if="item.goods_cover_thumb_mid" class="w-[100%] h-[350rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img(item.goods_cover_thumb_mid)" :mode="'aspectFill'" @error="item.goods_cover_thumb_mid='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[100%] h-[350rpx] rounded-tl-[var(--rounded-mid)] rounded-tr-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
<view class="px-[16rpx] flex-1 pt-[10rpx] pb-[20rpx] flex flex-col justify-between">
|
|
||||||
<view class="text-[] leading-[40rpx] text-[28rpx] multi-hidden">{{item.names}}</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx] mt-[10rpx] text-[var(--text-color-light9)]">已兑{{item.total_exchange_num}}人</view>
|
|
||||||
<view class="flex justify-between flex-wrap items-center mt-[16rpx]" >
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[var(--price-text-color)] price-font ml-[2rpx] flex items-center">
|
|
||||||
<text class="text-[32rpx]">{{ item.point }}</text>
|
|
||||||
<text class="text-[26rpx] ml-[4rpx]">积分</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="item.price&&item.price>0" class="flex items-center price-font mt-[6rpx]">
|
|
||||||
<text class="text-[var(--price-text-color)] font-400 text-[32rpx]">+{{ parseFloat(item.price).toFixed(2) }}</text>
|
|
||||||
<text class="text-[var(--price-text-color)] font-400 ml-[4rpx] text-[20rpx]">元</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-[120rpx] h-[54rpx] text-[22rpx] flex-center !text-[#fff] m-0 rounded-full primary-btn-bg remove-border text-center" shape="circle">去兑换</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!goodsList.length && loading" :option="{tip : '暂无商品'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
|
|
||||||
<tabbar />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, onMounted } from 'vue'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect, img } from '@/utils/common';
|
|
||||||
import { getExchangeGoodsList } from '@/addon/shop/api/point';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onShow, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const goodsList = ref<Array<any>>([]);
|
|
||||||
const coupon_id = ref<number | string>('');
|
|
||||||
const currGoodsCategory = ref<number | string>('');
|
|
||||||
const mescrollRef = ref(null);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const goods_name = ref("");
|
|
||||||
const price = ref("");
|
|
||||||
const sale_num = ref("");
|
|
||||||
const searchType = ref('total_order_num');
|
|
||||||
interface mescrollStructure {
|
|
||||||
num: number,
|
|
||||||
size: number,
|
|
||||||
endSuccess: Function,
|
|
||||||
[propName: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAllAppListFn = (mescroll: mescrollStructure) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
goods_category: currGoodsCategory.value,
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
names: goods_name.value,
|
|
||||||
coupon_id: coupon_id.value,
|
|
||||||
order: searchType.value === 'total_order_num' ? '' : searchType.value,
|
|
||||||
sort: searchType.value == 'price' ? price.value : sale_num.value
|
|
||||||
};
|
|
||||||
getExchangeGoodsList(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (Number(mescroll.num) === 1) {
|
|
||||||
goodsList.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
goodsList.value = goodsList.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索
|
|
||||||
const searchTypeFn = (type:string) => {
|
|
||||||
searchType.value = type;
|
|
||||||
if ( type == 'total_order_num') {
|
|
||||||
sale_num.value = '';
|
|
||||||
price.value = '';
|
|
||||||
}
|
|
||||||
if ( type == 'price') {
|
|
||||||
sale_num.value = '';
|
|
||||||
if(price.value){
|
|
||||||
price.value = price.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
}else{
|
|
||||||
price.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( type == 'total_exchange_num') {
|
|
||||||
price.value = '';
|
|
||||||
if(sale_num.value){
|
|
||||||
sale_num.value = sale_num.value == 'asc' ? 'desc' : 'asc';
|
|
||||||
}else{
|
|
||||||
sale_num.value = 'asc';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goodsList.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}
|
|
||||||
const toDetail = (id: string | number) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/point/detail', param: { id: id }, mode: 'navigateTo' })
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
getMescroll().optUp.textNoMore = t("end");
|
|
||||||
}, 500)
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.bg-color{
|
|
||||||
background: linear-gradient( 180deg, #EF000C 16%, rgba(239,0,12,0) 92%);
|
|
||||||
}
|
|
||||||
.nav-item.active {
|
|
||||||
color: $u-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-view-wrap {
|
|
||||||
word-break: keep-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-select {
|
|
||||||
color: var(--primary-color);
|
|
||||||
border-color: var(--primary-color);
|
|
||||||
background-color: var(--primary-color-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-popup .u-transition) {
|
|
||||||
top: 156rpx !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-warp {
|
|
||||||
z-index: 99999;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-bar-placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-tabbar__placeholder) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
:deep(.u-input__content__clear){
|
|
||||||
width: 28rpx;
|
|
||||||
height: 28rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
background-color: var(--text-color-light9);
|
|
||||||
}
|
|
||||||
.goods-item-style-two{
|
|
||||||
width: calc(50% - 10rpx);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden order-list" :style="themeColor()">
|
|
||||||
<view class="fixed left-0 top-0 right-0 z-10" v-if="statusLoading">
|
|
||||||
<scroll-view :scroll-x="true" class="tab-style-2">
|
|
||||||
<view class="tab-content">
|
|
||||||
<view class="tab-items" :class="{ 'class-select': orderState === item.status.toString() }" @click="orderStateFn(item.status)" v-for="(item, index) in orderStateList">{{ item.name }}</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<mescroll-body ref="mescrollRef" top="88rpx" @init="mescrollInit" :down="{ use: false }" @up="getShopOrderFn">
|
|
||||||
<view class="sidebar-margin pt-[var(--top-m)]" v-if="list.length">
|
|
||||||
<template v-for="(item, index) in list" :key="index">
|
|
||||||
<view class="mb-[var(--top-m)] card-template">
|
|
||||||
<view @click="toLink(item)">
|
|
||||||
<view class="flex justify-between items-center">
|
|
||||||
<view class="text-[#303133] text-[26rpx] font-400 leading-[30rpx]">
|
|
||||||
<text>{{ t('orderNo') }}:</text>
|
|
||||||
<text class="ml-[10rpx]">{{ item.order_no }}</text>
|
|
||||||
<text class="text-[303133] text-[26rpx] font-400 nc-iconfont nc-icon-fuzhiV6xx1 ml-[11rpx]" @click.stop="copy(item.order_no)"></text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[#303133] text-[26rpx] leading-[34rpx]" :class="{'text-primary': item.status == 1,'!text-[var(--text-color-light9)]' :item.status == 5 || item.status == -1}">{{ item.status_name.name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex box-border mt-[20rpx]" v-for="(subitem, index) in item.order_goods" :key="index">
|
|
||||||
|
|
||||||
<image v-if="subitem.goods_image_thumb_small" class="w-[150rpx] h-[150rpx] rounded-[var(--rounded-mid)]" :src="img(subitem.goods_image_thumb_small)" :mode="'aspectFill'" @error="subitem.goods_image_thumb_small='static/resource/images/diy/shop_default.jpg'"></image>
|
|
||||||
<image v-else class="w-[150rpx h-[150rpx] rounded-[var(--rounded-mid)]" :src="img('static/resource/images/diy/shop_default.jpg')" :mode="'aspectFill'"></image>
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col box-border">
|
|
||||||
<view class="max-w-[490rpx] text-[28rpx] leading-[40rpx] font-400 truncate text-[#303133]">{{ subitem.goods_name }}</view>
|
|
||||||
<view class="flex justify-between items-baseline text-[#303133] mt-[14rpx]">
|
|
||||||
<view>
|
|
||||||
<view v-if="subitem.sku_name" class="text-[24rpx] text-[var(--text-color-light6)] font-400 truncate leading-[34rpx] max-w-[369rpx] mb-[10rpx]">{{ subitem.sku_name }}</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx] text-[var(--text-color-light6)]" v-if="item.delivery_type != 'virtual'">
|
|
||||||
{{t('deliveryType') }} : {{item.delivery_type_name}}
|
|
||||||
</view>
|
|
||||||
<view class="text-[24rpx] font-400 leading-[34rpx] text-[var(--text-color-light6)]" v-else>{{t('createTime') }} :{{item.create_time}}</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx] font-400 w-[90rpx] leading-[36rpx]">x{{ subitem.num }}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end items-center mt-[20rpx]">
|
|
||||||
<view class="text-[22rpx] text-[var(--text-color-light9)] leading-[30rpx] mr-[6rpx]" v-if="parseFloat(item.delivery_money)">{{ t('service') }}</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="text-[22rpx] font-400 leading-[30rpx] text-[#303133]">{{ t('actualPayment') }}:</view>
|
|
||||||
<view class="text-[var(--price-text-color)] price-font">
|
|
||||||
<text class="text-[36rpx] mr-[2rpx]">{{ item.point }}</text>
|
|
||||||
<text class="text-[30rpx]">{{ t('point') }}</text>
|
|
||||||
<block v-if="parseFloat(item.order_money)">
|
|
||||||
<text class="text-[30rpx] mx-[4rpx]">+</text>
|
|
||||||
<text class="text-[36rpx] price-font">{{ parseFloat(item.order_money)}}</text>
|
|
||||||
<text class="text-[30rpx] price-font ml-[2rpx]">{{ t('money') }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end text-[28rpx] mt-[20rpx] items-center" v-if="(item.status == 1) || (item.status == 3) || (item.status == 5 && evaluateConfig.is_evaluate == 1)">
|
|
||||||
<view
|
|
||||||
class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full text-[var(--text-color-light6)] box-bordertext-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full text-[var(--text-color-light6)] box-border"
|
|
||||||
@click.stop="orderBtnFn(item, 'close')" v-if="item.status == 1">{{ t('orderClose') }}</view>
|
|
||||||
<view
|
|
||||||
class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid text-[#fff] border-primary bg-primary rounded-full ml-[20rpx] box-border"
|
|
||||||
@click.stop="orderBtnFn(item, 'pay')" v-if="item.status == 1">{{ t('topay') }}</view>
|
|
||||||
<view
|
|
||||||
class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid text-[#fff] border-primary bg-primary rounded-full ml-[20rpx] box-border"
|
|
||||||
@click.stop="orderBtnFn(item, 'finish')" v-if="item.status == 3">{{ t('orderFinish') }}</view>
|
|
||||||
<view
|
|
||||||
class="text-[24rpx] font-500 leading-[52rpx] h-[56rpx] min-w-[150rpx] text-center border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx] text-[var(--text-color-light6)] box-border"
|
|
||||||
v-if="item.status == 5 && evaluateConfig.is_evaluate == 1"
|
|
||||||
@click.stop="orderBtnFn(item, 'evaluate')">{{ item.is_evaluate == 1 ? t('selectedEvaluate') : t('evaluate') }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty v-if="!list.length && loading" :option="{tip : '暂无订单'}"></mescroll-empty>
|
|
||||||
</mescroll-body>
|
|
||||||
<pay ref="payRef" @close="payClose"></pay>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect,copy } from '@/utils/common';
|
|
||||||
import { getShopOrderStatus, getShopOrder, orderClose, orderFinish } from '@/addon/shop/api/order';
|
|
||||||
import { getEvaluateConfig } from '@/addon/shop/api/shop';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
import useConfigStore from "@/stores/config";
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const statusLoading = ref<boolean>(false);
|
|
||||||
const orderState = ref('')
|
|
||||||
const orderStateList: any = ref([]);
|
|
||||||
const evaluateConfig = ref("")
|
|
||||||
|
|
||||||
const mch_id = ref('')
|
|
||||||
const isTradeManaged = ref(false)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
orderState.value = option.status || "";
|
|
||||||
evaluateEvent()
|
|
||||||
getShopOrderStatusFn();
|
|
||||||
});
|
|
||||||
|
|
||||||
const evaluateEvent = () => {
|
|
||||||
getEvaluateConfig().then((data: any) => {
|
|
||||||
evaluateConfig.value = data.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getShopOrderFn = (mescroll: any) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data: object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size,
|
|
||||||
status: orderState.value,
|
|
||||||
activity_type:'exchange'
|
|
||||||
};
|
|
||||||
|
|
||||||
getShopOrder(data).then((res: any) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
|
|
||||||
mch_id.value = res.data.mch_id;
|
|
||||||
isTradeManaged.value = res.data.is_trade_managed;
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getShopOrderStatusFn = () => {
|
|
||||||
statusLoading.value = false;
|
|
||||||
orderStateList.value = [];
|
|
||||||
let obj = { name: '全部', status: '' };
|
|
||||||
orderStateList.value.push(obj);
|
|
||||||
|
|
||||||
getShopOrderStatus().then((res: any) => {
|
|
||||||
Object.values(res.data).forEach((item, index) => {
|
|
||||||
orderStateList.value.push(item);
|
|
||||||
});
|
|
||||||
statusLoading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
statusLoading.value = true;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const orderStateFn = (status: any) => {
|
|
||||||
orderState.value = status.toString();
|
|
||||||
list.value = [];
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
};
|
|
||||||
|
|
||||||
const toLink = (data: any) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: data.order_id } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付
|
|
||||||
const payRef = ref(null)
|
|
||||||
const orderBtnFn = (data: any, type = '') => {
|
|
||||||
if (type == 'pay')
|
|
||||||
payRef.value?.open(data.order_type, data.order_id, `/addon/shop/pages/order/detail?order_id=${data.order_id}`);
|
|
||||||
else if (type == 'close') {
|
|
||||||
close(data);
|
|
||||||
} else if (type == 'finish') {
|
|
||||||
finish(data);
|
|
||||||
} else if (type == 'evaluate') {
|
|
||||||
if (!data.is_evaluate) {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate', param: { order_id: data.order_id } })
|
|
||||||
} else {
|
|
||||||
redirect({ url: '/addon/shop/pages/evaluate/order_evaluate_view', param: { order_id: data.order_id } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//关闭订单
|
|
||||||
const close = (item: any) => {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定要关闭该订单吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderClose(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//订单完成
|
|
||||||
const finish = (item: any) => {
|
|
||||||
// 如果不在微信小程序中
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 检测微信小程序是否已开通发货信息管理服务
|
|
||||||
if (item.pay && item.pay.type == 'wechatpay' && isTradeManaged.value && wx.openBusinessView) {
|
|
||||||
wx.openBusinessView({
|
|
||||||
businessType: 'weappOrderConfirm',
|
|
||||||
extraData: {
|
|
||||||
merchant_id: mch_id.value,
|
|
||||||
merchant_trade_no: item.out_trade_no
|
|
||||||
},
|
|
||||||
success: (res:any) => {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: (res:any) => {
|
|
||||||
console.log('小程序确认收货组件打开失败 fail', res);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定物品已收到吗?',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
success: res => {
|
|
||||||
if (res.confirm) {
|
|
||||||
orderFinish(item.order_id).then((data) => {
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.order-list .mescroll-body {
|
|
||||||
padding-bottom: constant(safe-area-inset-bottom) !important;
|
|
||||||
padding-bottom: env(safe-area-inset-bottom) !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-item {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-color {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-color {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.class-select {
|
|
||||||
position: relative;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--primary-color);
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
height: 4rpx;
|
|
||||||
border-radius: 4rpx;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
width: 40rpx;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,409 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh]" v-if="orderData">
|
|
||||||
<view class="pt-[30rpx] sidebar-margin payment-bottom">
|
|
||||||
<!-- 配送方式 -->
|
|
||||||
<view class="mb-[var(--top-m)] rounded-[var(--rounded-big)] bg-white" v-if="orderData.basic.has_goods_types.includes('real') && delivery_type_list.length">
|
|
||||||
<view class="rounded-tl-[var(--rounded-big)] rounded-tr-[var(--rounded-big)] head-tab flex items-center w-full bg-[#f1f1f1]" v-if="delivery_type_list.length > 1">
|
|
||||||
<view v-for="(item, index) in delivery_type_list" :key="index" class="head-tab-item flex-1 relative" :class="{'active': index === activeIndex}">
|
|
||||||
<view class="h-[74rpx] relative z-10 text-center leading-[74rpx] text-[28rpx]" @click="switchDeliveryType(item.key, index)">
|
|
||||||
{{ item.name }}
|
|
||||||
</view>
|
|
||||||
<image v-if="index === activeIndex && delivery_type_list.length == 3" class="tab-image absolute bottom-[-2rpx] h-[94rpx] w-[240rpx]" :src="img(`addon/shop/payment/tab_${index}.png`)" mode="aspectFit"></image>
|
|
||||||
<image v-else-if="index === activeIndex && delivery_type_list.length == 2" class="tab-img absolute bottom-[-2rpx] h-[95rpx] w-[354rpx]" :src="img(`addon/shop/payment/tabstyle_${index}.png`)" mode="aspectFit"></image>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="min-h-[140rpx] flex items-center px-[30rpx]">
|
|
||||||
<!-- 收货地址 -->
|
|
||||||
<view class="w-full" v-if="['express', 'local_delivery'].includes(createData.delivery.delivery_type)" @click="toSelectAddress">
|
|
||||||
<view v-if="!$u.test.isEmpty(orderData.delivery.take_address)" class="pt-[20rpx] pb-[30rpx] flex items-center">
|
|
||||||
<image class="w-[60rpx] h-[60rpx] mr-[20rpx] flex-shrink-0" :src="img('addon/shop/payment/position_01.png')" mode="aspectFit"></image>
|
|
||||||
<view class="flex flex-col overflow-hidden">
|
|
||||||
<text class="text-[26rpx] text-[var(--text-color-light9)] mt-[16rpx] truncate max-w-[536rpx]">{{orderData.delivery.take_address.full_address.split(orderData.delivery.take_address.address)[0]}}</text>
|
|
||||||
<text class="font-500 text-[30rpx] mt-[14rpx] text-[#333] truncate max-w-[536rpx]">{{orderData.delivery.take_address.address}}</text>
|
|
||||||
<view class="flex items-center text-[26rpx] text-[var(--text-color-light6)] mt-[16rpx]">
|
|
||||||
<text class="mr-[16rpx]">{{ orderData.delivery.take_address.name }}</text>
|
|
||||||
<text>{{ mobileHide(orderData.delivery.take_address.mobile) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center">
|
|
||||||
<image class="w-[26rpx] h-[30rpx] mr-[10rpx]" :src="img('addon/shop/payment/position_02.png')" mode="aspectFit"></image>
|
|
||||||
<text class="text-[28rpx]">添加收货地址</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)] ml-auto"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 自提点 -->
|
|
||||||
<view class="flex items-center w-full flex items-center" v-if="createData.delivery.delivery_type == 'store'" @click="storeRef.open()">
|
|
||||||
<view v-if="!$u.test.isEmpty(orderData.delivery.take_store)" class="pt-[26rpx] pb-[30rpx] w-full flex items-centerv">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[30rpx] font-500 text-[#303133] mb-[20rpx]">{{ orderData.delivery.take_store.store_name }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] mb-[14rpx]">门店地址:{{ orderData.delivery.take_store.full_address }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] mb-[14rpx]">联系电话:{{ orderData.delivery.take_store.store_mobile }}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)]">营业时间:{{ orderData.delivery.take_store.trade_time }}</view>
|
|
||||||
</view>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<view v-else class="flex items-center w-full">
|
|
||||||
<image class="w-[26rpx] h-[30rpx] mr-[10rpx]" :src="img('addon/shop/payment/position_02.png')" mode="aspectFit"></image>
|
|
||||||
<text class="text-[28rpx]">请选择自提点</text>
|
|
||||||
<text class="ml-auto nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mb-[var(--top-m)] card-template h-[100rpx] flex items-center" v-if="orderData.basic.has_goods_types.includes('real') && !delivery_type_list.length">
|
|
||||||
<p class="text-[28rpx] text-[var(--primary-color)]">商家尚未配置配送方式</p>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="mb-[var(--top-m)] card-template">
|
|
||||||
<view class="mb-[30rpx]">
|
|
||||||
<view class="flex" v-for="(item, key, index) in orderData.goods_data" :key="index" :class="{'pb-[40rpx]': (index + 1) != Object.keys(orderData.goods_data).length}">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="180rpx" height="180rpx" :src="img(item.sku_image.split(',')[0])" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[180rpx] h-[180rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"/>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex flex-1 w-0 flex-col justify-between ml-[20rpx] py-[6rpx]">
|
|
||||||
<view class="line-normal">
|
|
||||||
<view class="truncate text-[#303133] text-[28rpx] leading-[32rpx]">
|
|
||||||
{{ item.goods.goods_name }}
|
|
||||||
</view>
|
|
||||||
<view v-if="item.sku_name" class="mt-[14rpx] flex">
|
|
||||||
<text class="truncate text-[24rpx] text-[var(--text-color-light9)] leading-[28rpx]">{{ item.sku_name }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mb-auto" :class="{'mt-[6rpx]': !item.sku_name}" v-if="item.not_support_delivery">
|
|
||||||
<u-alert type="error" description="该商品不支持当前所选配送方式" class="leading-[30rpx] !inline-block" fontSize="11"></u-alert>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-baseline">
|
|
||||||
<view class="text-[var(--price-text-color)] flex items-baseline price-font">
|
|
||||||
<view class="flex items-baseline price-font">
|
|
||||||
<text class="text-[40rpx] font-200">{{item.exchange_info.point}}</text>
|
|
||||||
<text class="text-[32rpx]">积分</text>
|
|
||||||
</view>
|
|
||||||
<block v-if="parseFloat(item.price)">
|
|
||||||
<text class="mx-[4rpx] text-[32rpx]">+</text>
|
|
||||||
<view class="flex items-baseline price-font">
|
|
||||||
<text class="text-[40rpx] font-200">{{ parseFloat(item.price).toFixed(2) }}</text>
|
|
||||||
<text class="text-[32rpx]">元</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<view class="font-400 text-[28rpx] text-[#303133]">
|
|
||||||
<text>x</text>
|
|
||||||
<text>{{ item.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 买家留言 -->
|
|
||||||
<view class="bg-white flex items-center leading-[30rpx]">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] text-[#303133]">买家留言</view>
|
|
||||||
<view class="flex-1 text-[#303133]">
|
|
||||||
<input type="text" v-model="createData.member_remark" class="text-right text-[#333] text-[28rpx]" maxlength="50" placeholder="请输入留言信息给卖家" placeholder-class="text-[var(--text-color-light9)] text-[28rpx]">
|
|
||||||
</view>
|
|
||||||
<!-- <text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text> -->
|
|
||||||
</view>
|
|
||||||
<!-- 发票 -->
|
|
||||||
<view class="flex items-center text-[#303133] leading-[30rpx] mt-[30rpx]" @click="invoiceRef.open()" v-if="invoiceRef && invoiceRef.invoiceOpen">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] text-[#303133]">发票信息</view>
|
|
||||||
<view class="flex-1 w-0 text-right truncate">
|
|
||||||
<text class="text-[28rpx] text-[#333]">{{ createData.invoice.header_name || '不需要发票' }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="card-template">
|
|
||||||
<view class="title">价格明细</view>
|
|
||||||
<view class="card-template-item">
|
|
||||||
<view class="text-[28rpx] w-[150rpx] leading-[30rpx] text-[#303133]">商品金额</view>
|
|
||||||
<view class="flex-1 w-0 text-right price-font text-[#333] text-[32rpx]">
|
|
||||||
<view class="inline-block">
|
|
||||||
<text class="text-[32rpx] mr-[2rpx]">{{ orderData.basic.point_sum }}</text>
|
|
||||||
<text class="text-[30rpx]">积分</text>
|
|
||||||
</view>
|
|
||||||
<block v-if="orderData.basic && parseFloat(orderData.basic.goods_money)">
|
|
||||||
<text class="text-[28rpx] mx-[4rpx]">+</text>
|
|
||||||
<view class="inline-block">
|
|
||||||
<text class="text-[32rpx] mr-[2rpx]">{{ parseFloat(orderData.basic.goods_money).toFixed(2) }}</text>
|
|
||||||
<text class="text-[30rpx]">元</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item" v-if="orderData.basic.delivery_money">
|
|
||||||
<view class="text-[26rpx] w-[150rpx] leading-[30rpx] text-[#303133]">配送费用</view>
|
|
||||||
<view class="flex-1 w-0 text-right price-font text-[#333] text-[32rpx]">
|
|
||||||
¥{{ parseFloat(orderData.basic.delivery_money) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item" v-if="orderData.basic.discount_money">
|
|
||||||
<view class="text-[26rpx] w-[150rpx] leading-[30rpx] text-[#303133]">优惠金额</view>
|
|
||||||
<view class="flex-1 w-0 text-right text-[var(--price-text-color)] text-[32rpx] price-font leading-[1]">
|
|
||||||
-¥{{ parseFloat(orderData.basic.discount_money) }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true">
|
|
||||||
<view class="flex-1 flex items-center justify-between pl-[30rpx] pr-[20rpx]">
|
|
||||||
<view class="flex items-baseline">
|
|
||||||
<text class="text-[26rpx] text-[#333] leading-[32rpx]">合计:</text>
|
|
||||||
<text class="text-[var(--price-text-color)] price-font inline-block">
|
|
||||||
<text class="text-[44rpx]">{{ orderData.basic.point_sum }}</text>
|
|
||||||
<text class="text-[38rpx]">积分</text>
|
|
||||||
</text>
|
|
||||||
<block v-if="orderData.basic && parseFloat(orderData.basic.goods_money)">
|
|
||||||
<text class="text-[38rpx] text-[var(--price-text-color)] price-font mx-[4rpx]">+</text>
|
|
||||||
<view class="inline-block">
|
|
||||||
<text class="text-[44rpx] text-[var(--price-text-color)] price-font">{{ parseFloat(orderData.basic.order_money).toFixed(2) }}</text>
|
|
||||||
<text class="text-[38rpx] text-[var(--price-text-color)] price-font">元</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
<button class="primary-btn-bg w-[196rpx] h-[70rpx] font-500 text-[26rpx] leading-[70rpx] !text-[#fff] !border-[0] rounded-[100rpx] m-0" hover-class="none" @click="create">提交订单</button>
|
|
||||||
</view>
|
|
||||||
</u-tabbar>
|
|
||||||
<!-- 选择自提点 -->
|
|
||||||
<select-store ref="storeRef" @confirm="confirmSelectStore" />
|
|
||||||
<!-- 发票 -->
|
|
||||||
<invoice ref="invoiceRef" @confirm="confirmInvoice" />
|
|
||||||
<!-- 地址 -->
|
|
||||||
<address-list ref="addressRef" @confirm="confirmAddress" />
|
|
||||||
|
|
||||||
<pay ref="payRef" @close="payClose" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, watch } from 'vue'
|
|
||||||
import { orderCreateCalculate, orderCreate } from '@/addon/shop/api/point'
|
|
||||||
import { redirect, img, moneyFormat, mobileHide } from '@/utils/common'
|
|
||||||
import selectStore from './../order/components/select-store/select-store'
|
|
||||||
import invoice from './../order/components/invoice/invoice'
|
|
||||||
import addressList from './components/address-list/address-list'
|
|
||||||
import { useSubscribeMessage } from '@/hooks/useSubscribeMessage'
|
|
||||||
|
|
||||||
const createData: any = ref({
|
|
||||||
order_key: '',
|
|
||||||
member_remark: '',
|
|
||||||
discount: {},
|
|
||||||
invoice: {},
|
|
||||||
delivery: {
|
|
||||||
delivery_type: ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const orderData = ref(null)
|
|
||||||
const storeRef = ref()
|
|
||||||
const payRef = ref()
|
|
||||||
const invoiceRef = ref()
|
|
||||||
const createLoading = ref(false)
|
|
||||||
const activeIndex = ref(0)//配送方式激活
|
|
||||||
const delivery_type_list = ref([])
|
|
||||||
const addressRef = ref()
|
|
||||||
uni.getStorageSync('orderCreateData') && Object.assign(createData.value, uni.getStorageSync('orderCreateData'))
|
|
||||||
|
|
||||||
// 选择地址之后跳转回来
|
|
||||||
const selectAddress = uni.getStorageSync('selectAddressCallback')
|
|
||||||
if (selectAddress) {
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = selectAddress.delivery
|
|
||||||
createData.value.delivery.take_address_id = selectAddress.address_id
|
|
||||||
uni.removeStorage({ key: 'selectAddressCallback' })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换配送方式
|
|
||||||
const switchDeliveryType = (type: string, index: number) => {
|
|
||||||
if (createData.value.delivery.delivery_type != type) {
|
|
||||||
activeIndex.value = index
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = type
|
|
||||||
createData.value.delivery.take_address_id = 0
|
|
||||||
calculate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单计算
|
|
||||||
*/
|
|
||||||
const calculate = () => {
|
|
||||||
orderCreateCalculate(createData.value).then(({data}) => {
|
|
||||||
orderData.value = data
|
|
||||||
createData.value.order_key = data.order_key
|
|
||||||
if (orderData.value.delivery.delivery_type_list) {
|
|
||||||
delivery_type_list.value = Object.values(orderData.value.delivery.delivery_type_list)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectAddress) activeIndex.value = delivery_type_list.value.findIndex(el => el.key === orderData.value.delivery.delivery_type)
|
|
||||||
!createData.value.delivery.delivery_type && data.delivery.delivery_type && (createData.value.delivery.delivery_type = data.delivery.delivery_type)
|
|
||||||
}).catch()
|
|
||||||
}
|
|
||||||
calculate()
|
|
||||||
|
|
||||||
// 改变配送方式
|
|
||||||
watch(
|
|
||||||
() => delivery_type_list.value.length,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
if(delivery_type_list.value.length && uni.getStorageSync('distributionType')){
|
|
||||||
delivery_type_list.value.forEach((item: any,index: any)=>{
|
|
||||||
if(item.name == uni.getStorageSync('distributionType')){
|
|
||||||
activeIndex.value = index;
|
|
||||||
switchDeliveryType(item.key, index)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
uni.removeStorage({ key: 'distributionType' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let orderId = 0
|
|
||||||
/**
|
|
||||||
* 订单创建
|
|
||||||
*/
|
|
||||||
const create = () => {
|
|
||||||
if (!verify() || createLoading.value) return
|
|
||||||
createLoading.value = true
|
|
||||||
|
|
||||||
useSubscribeMessage().request('shop_order_pay,shop_order_delivery')
|
|
||||||
|
|
||||||
orderCreate(createData.value).then(({ data }) => {
|
|
||||||
orderId = data.order_id
|
|
||||||
if (orderData.value.basic.order_money == 0) {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: orderId }, mode: 'redirectTo' })
|
|
||||||
} else {
|
|
||||||
payRef.value?.open(data.trade_type, data.order_id, `/addon/shop/pages/order/detail?order_id=${ data.order_id }`)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
createLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下单校验
|
|
||||||
*/
|
|
||||||
const verify = () => {
|
|
||||||
const data = createData.value
|
|
||||||
let verify = true
|
|
||||||
|
|
||||||
if (orderData.value.basic.has_goods_types.includes('real')) {
|
|
||||||
if (['express', 'local_delivery'].includes(data.delivery.delivery_type) && !orderData.value.delivery.take_address) {
|
|
||||||
uni.showToast({ title: '请选择收货地址', icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.delivery.delivery_type == 'store' && !data.delivery.take_store_id) {
|
|
||||||
uni.showToast({ title: '请选择自提点', icon: 'none' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return verify
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付弹窗关闭
|
|
||||||
*/
|
|
||||||
const payClose = () => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: orderId }, mode: 'redirectTo' })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择地址
|
|
||||||
*/
|
|
||||||
const toSelectAddress = () => {
|
|
||||||
let data: any = {};
|
|
||||||
data.delivery = createData.value.delivery.delivery_type;
|
|
||||||
data.type = createData.value.delivery.delivery_type == 'local_delivery' ? 'location_address' : 'address';
|
|
||||||
data.id = orderData.value.delivery.take_address.id;
|
|
||||||
addressRef.value.open(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择自提点
|
|
||||||
*/
|
|
||||||
const confirmSelectStore = (store: any) => {
|
|
||||||
createData.value.delivery.take_store_id = ((store && store.store_id) ? store.store_id: 0)
|
|
||||||
calculate()
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmInvoice = (invoice: object) => {
|
|
||||||
createData.value.invoice = invoice
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmAddress = (data:object) => {
|
|
||||||
createData.value.order_key = ''
|
|
||||||
createData.value.delivery.delivery_type = data.delivery
|
|
||||||
createData.value.delivery.take_address_id = data.address_id
|
|
||||||
calculate();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.head-tab{
|
|
||||||
.head-tab-item{
|
|
||||||
.tab-image{
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
&:nth-child(1).active{
|
|
||||||
view{
|
|
||||||
padding-right: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:nth-child(2){
|
|
||||||
.tab-image{
|
|
||||||
width: 312rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:nth-child(3).active{
|
|
||||||
view{
|
|
||||||
padding-left: 30rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.active{
|
|
||||||
view{
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tab-img{
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.u-alert) {
|
|
||||||
padding: 6rpx 16rpx !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
.alert-wrap{
|
|
||||||
display: inline-block !important;
|
|
||||||
:deep(.u-fade-enter-active){
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-ellipsis {
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.line-normal{
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
.payment-bottom{
|
|
||||||
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|
||||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<swiper :indicator-dots="false" :autoplay="false" :disable-touch="true" :current="step" class="h-screen" :duration="300" v-if="detail">
|
|
||||||
<swiper-item>
|
|
||||||
<scroll-view scroll-y="true" class="bg-page min-h-screen overflow-hidden">
|
|
||||||
<view class="m-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="w-[120rpx] h-[120rpx] flex items-center justify-center">
|
|
||||||
<u--image :radius="'var(--goods-rounded-small)'" width="120rpx" height="120rpx" :src="img(orderDetail.sku_image.split(',')[0])" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[120rpx] h-[120rpx] rounded-[var(--goods-rounded-small)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="flex-1 w-0 ml-[20rpx]">
|
|
||||||
<view class="text-ellipsis text-[28rpx] leading-normal truncate">{{orderDetail.goods_name}}</view>
|
|
||||||
<view v-if="orderDetail.sku_name" class="mt-[6rpx] text-[24rpx] leading-[1.3] text-[var(--text-color-light9)] truncate">{{ orderDetail.sku_name }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)] flex items-center" @click="selectRefundType(1)">
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx]">仅退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]" v-if="orderDetail.goods_type == 'real'">未收到货,或与商家协商一致不用退货只退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]" v-else-if="orderDetail.goods_type == 'virtual'">与商家协商一致不用退货只退款</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[28rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="py-[var(--pad-top-m)] flex items-center border-0 !border-t !border-[#f5f5f5] border-solid" v-if="orderDetail.goods_type == 'real' && (!orderDetail.delivery_status || orderDetail.delivery_status != 'wait_delivery')" @click="selectRefundType(2)">
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx]">退货退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]">已收到货,需退还收到的货物</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[28rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</swiper-item>
|
|
||||||
<swiper-item>
|
|
||||||
<scroll-view scroll-y="true" class="bg-page min-h-screen overflow-hidden">
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)] flex justify-between items-center">
|
|
||||||
<view class="text-[28rpx]">退款原因</view>
|
|
||||||
<view class="flex ml-[auto] items-center h-[30rpx]" @click="refundCausePopup = true">
|
|
||||||
<text class="text-[26rpx] text-[var(--text-color-light9)] truncate max-w-[460rpx]">{{ formData.reason || '请选择' }}</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx pt-[4rpx] text-[24rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)]">
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<view class="text-[28rpx] font-500">退款金额</view>
|
|
||||||
<view class="flex justify-end items-center text-[var(--price-text-color)] price-font">
|
|
||||||
<text class="font-500 text-[36rpx] leading-none">¥</text>
|
|
||||||
<!-- <input type="digit" v-model.number="formData.apply_money" class="font-500 text-[36rpx] leading-none" :style="{ width: inputWidth(formData.apply_money) }" @blur="handleInput"> -->
|
|
||||||
<text class="font-500 text-[36rpx] leading-none">{{ formData.apply_money }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-right text-[24rpx] text-[var(--text-color-light9)] mt-[10rpx]">
|
|
||||||
<!-- <text>最多可退¥{{ refundMoney.refund_money }}</text> -->
|
|
||||||
<text v-if="refundMoney.is_refund_delivery === 1 && Number(refundMoney.refund_delivery_money) > 0" class="ml-[10rpx]">(包含运费¥{{ refundMoney.refund_delivery_money }})</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="pt-[var(--pad-top-m)] pb-[14rpx] ">
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="font-500">上传凭证</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)] ml-[10rpx]">选填</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[30rpx]">
|
|
||||||
<u-upload :fileList="voucherListPreview" @afterRead="afterRead" @delete="deletePic" multiple :maxCount="9"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)]">
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="font-500">补充描述</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)] ml-[10rpx]">选填</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[30rpx] h-[200rpx]">
|
|
||||||
<textarea class="leading-[1.5] h-[100%] w-[100%] text-[28rpx]" v-model="formData.remark" cols="30" rows="5" placeholder="补充描述,有助于更好的处理售后问题" placeholder-class="text-[26rpx] text-[var(--text-color-light9)]"></textarea>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-full">
|
|
||||||
<view class="py-[var(--top-m)] px-[var(--sidebar-m)] box-border">
|
|
||||||
<button class="primary-btn-bg !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" :loading="operateLoading" @click="save">提交</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 退款原因 -->
|
|
||||||
<u-popup :show="refundCausePopup" @close="refundCausePopup = false">
|
|
||||||
<view class="popup-common" @touchmove.prevent.stop>
|
|
||||||
<view class="title">退款原因</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[450rpx] px-[30rpx] box-border">
|
|
||||||
<u-radio-group v-model="currReasonName" placement="column" iconPlacement="right">
|
|
||||||
<u-radio activeColor="var(--primary-color)" :labelSize="'30rpx'" labelColor="#333" :customStyle="{marginBottom: '34rpx'}" v-for="(item, index) in reason" :key="index" :label="item" :name="item"></u-radio>
|
|
||||||
</u-radio-group>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="refundCausePopupFn">确定</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</scroll-view>
|
|
||||||
</swiper-item>
|
|
||||||
</swiper>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { redirect, img, moneyFormat, goback } from '@/utils/common'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { getShopOrderDetail } from '@/addon/shop/api/order'
|
|
||||||
import { getRefundReason, applyRefund,getRefundMoney } from '@/addon/shop/api/refund'
|
|
||||||
import { uploadImage } from '@/app/api/system'
|
|
||||||
import {useSubscribeMessage} from "@/hooks/useSubscribeMessage";
|
|
||||||
|
|
||||||
const detail = ref(null)
|
|
||||||
const orderDetail = ref({})
|
|
||||||
const orderGoodsId = ref(0)
|
|
||||||
const step = ref(0)
|
|
||||||
const refundCausePopup = ref(false)
|
|
||||||
const formData = ref({
|
|
||||||
order_id: detail.value?.order_id,
|
|
||||||
order_goods_id: orderGoodsId.value,
|
|
||||||
refund_type: '',
|
|
||||||
apply_money: '',
|
|
||||||
reason: '',
|
|
||||||
remark: '',
|
|
||||||
voucher: []
|
|
||||||
})
|
|
||||||
const refundMoney = ref<any>({})
|
|
||||||
const reason = ref<string[]>([])
|
|
||||||
const currReasonName = ref('')
|
|
||||||
|
|
||||||
getRefundReason().then(({ data }) => {
|
|
||||||
reason.value = data
|
|
||||||
if(reason.value && reason.value.length) currReasonName.value = reason.value[0];
|
|
||||||
})
|
|
||||||
|
|
||||||
onLoad((data) => {
|
|
||||||
orderGoodsId.value = data.order_goods_id || 0
|
|
||||||
formData.value.order_goods_id = orderGoodsId.value
|
|
||||||
formData.value.order_id = data.order_id || 0
|
|
||||||
if(data.order_id && data.order_goods_id){
|
|
||||||
getShopOrderDetail(data.order_id).then(({ data }) => {
|
|
||||||
detail.value = data
|
|
||||||
detail.value.order_goods.forEach((item,index)=>{
|
|
||||||
if(orderGoodsId.value == item.order_goods_id){
|
|
||||||
orderDetail.value = item;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
formData.value.apply_money = moneyFormat(refundMoney.value.refund_money)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取可退款金额
|
|
||||||
getRefundMoney({order_goods_id: data.order_goods_id}).then(res =>{
|
|
||||||
refundMoney.value = res.data
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/order/list',
|
|
||||||
title: '缺少订单id'
|
|
||||||
};
|
|
||||||
goback(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const inputWidth = computed((value) => {
|
|
||||||
return function (value) {
|
|
||||||
if (value == '' || value == 0) {
|
|
||||||
return '70rpx';
|
|
||||||
} else {
|
|
||||||
return String(value).length * 17 + 'rpx';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectRefundType = (type : number) => {
|
|
||||||
formData.value.refund_type = type
|
|
||||||
step.value = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
const voucherListPreview = computed(() => {
|
|
||||||
return formData.value.voucher.map(item => {
|
|
||||||
return {url: img(item)}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const afterRead = (event: any) => {
|
|
||||||
event.file.forEach(item => {
|
|
||||||
uploadImage({
|
|
||||||
filePath: item.url,
|
|
||||||
name: 'file'
|
|
||||||
}).then(res => {
|
|
||||||
if (formData.value.voucher.length < 9 ) {
|
|
||||||
formData.value.voucher.push(res.data.url)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const deletePic = (event: any)=> {
|
|
||||||
formData.value.voucher.splice(event.index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const operateLoading = ref(false)
|
|
||||||
const save = ()=> {
|
|
||||||
|
|
||||||
if(!formData.value.reason){
|
|
||||||
uni.showToast({
|
|
||||||
title: '请选择退款原因',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((Number(formData.value.apply_money).toFixed(2)) < 0 ){
|
|
||||||
uni.showToast({
|
|
||||||
title: '退款金额不能为0,保留两位小数',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Number(formData.value.apply_money)>Number(refundMoney.value.refund_money)) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '退款金额不能大于可退款总额',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operateLoading.value) return
|
|
||||||
operateLoading.value = true
|
|
||||||
|
|
||||||
useSubscribeMessage().request('shop_refund_agree,shop_refund_refuse')
|
|
||||||
|
|
||||||
applyRefund(formData.value).then((res) => {
|
|
||||||
operateLoading.value = false
|
|
||||||
setTimeout(()=> {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: formData.value.order_id } })
|
|
||||||
}, 1000)
|
|
||||||
}).catch(() => {
|
|
||||||
operateLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundCausePopupFn = ()=>{
|
|
||||||
formData.value.reason = currReasonName.value;
|
|
||||||
refundCausePopup.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleInput = (event:any) =>{
|
|
||||||
if(Number(event.detail.value) > Number(refundMoney.value.refund_money)){
|
|
||||||
uni.showToast({
|
|
||||||
title: '退款金额不能大于可退款总额',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
:deep(.u-upload__button) {
|
|
||||||
width: 70px !important;
|
|
||||||
height: 70px !important;
|
|
||||||
border: 1px dashed #ddd;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 20rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-upload__wrap__preview__image) {
|
|
||||||
width: 70px!important;
|
|
||||||
height: 70px!important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,369 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="!loading">
|
|
||||||
<view class="pb-[200rpx]" v-if="type != 'logistics'">
|
|
||||||
<view class="bg-linear">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
|
|
||||||
<!-- #endif -->
|
|
||||||
<view v-if="detail.status_name" class="flex justify-between items-center pl-[40rpx] pr-[50rpx] h-[280rpx] box-border pb-[90rpx]">
|
|
||||||
<view class="text-[36rpx] font-500 leading-[42rpx] text-[#fff]">{{ detail.status_name }}</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<image v-if="['1','2','4','6','7'].indexOf(detail.status) != -1" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/payment.png')" mode="aspectFit"/>
|
|
||||||
<image v-if="['8'].indexOf(detail.status) != -1" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/complete.png')" mode="aspectFit" />
|
|
||||||
<image v-if="['3','5','-1'].indexOf(detail.status) != -1" class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/close.png')" mode="aspectFit" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin card-template flex justify-between flex-wrap mt-[-76rpx]">
|
|
||||||
<view class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" @click="goodsEvent(detail.order_goods.goods_id)">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="150rpx" height="150rpx" :src="img(detail.order_goods.goods_image_thumb_small ? detail.order_goods.goods_image_thumb_small : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
|
|
||||||
<view>
|
|
||||||
<view class="text-[28rpx] max-w-[490rpx] truncate leading-[40rpx]">{{ detail.order_goods.goods_name }}</view>
|
|
||||||
<view class="text-[22rpx] mt-[10rpx] text-[var(--text-color-light9)] truncate max-w-[490rpx] leading-[28rpx]" v-if="detail.order_goods.sku_name">{{ detail.order_goods.sku_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-center leading-[28rpx] ">
|
|
||||||
<view class="price-font">
|
|
||||||
<text class="text-[24rpx]">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(detail.order_goods.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(detail.order_goods.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx]">x{{ detail.order_goods.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template">
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('refundMoney')}}</view>
|
|
||||||
<view class="price-font text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[24rpx] mr-[4rpx]">¥</text>
|
|
||||||
<text class="text-[28rpx]" v-if="detail.status == 8">{{ parseFloat(detail.money).toFixed(2) }}</text>
|
|
||||||
<text class="text-[28rpx]" v-else>{{ parseFloat(detail.apply_money).toFixed(2) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('refundType')}}</view>
|
|
||||||
<view>{{ detail.refund_type_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('refundCause')}}</view>
|
|
||||||
<view class="w-[400rpx] multi-hidden text-right">{{ detail.reason || '--' }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('refundNo')}}</view>
|
|
||||||
<view>{{ detail.order_refund_no }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('createTime')}}</view>
|
|
||||||
<view>{{ detail.create_time }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item !items-baseline">
|
|
||||||
<view>{{t('createExplain')}}</view>
|
|
||||||
<view class="flex-1 ml-[60rpx] text-right leading-[1.5] flex justify-end break-all">{{ detail.remark }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item !items-baseline break-all" v-if="detail.shop_reason">
|
|
||||||
<view>{{t('reasonRefusal')}}</view>
|
|
||||||
<view class="flex-1 ml-[60rpx] leading-[1.5] text-right text-[#333]">{{ detail.shop_reason }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="sidebar-margin mt-[var(--top-m)] card-template">
|
|
||||||
<view class="justify-between text-[28rpx] card-template-item">
|
|
||||||
<view>{{t('record')}}</view>
|
|
||||||
<view class="flex items-center" @click="redirect({url: '/addon/shop/pages/refund/log', param: { order_refund_no: orderRefundNo }})">
|
|
||||||
<text class="text-[26rpx] text-[var(--text-color-light9)]">{{t('check')}}</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[24rpx] text-[var(--text-color-light9)] pt-[2rpx]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="flex tab-bar justify-between items-center bg-[#fff] fixed left-0 right-0 bottom-0 min-h-[100rpx] pl-[30rpx] pr-[20rpx] flex-wrap">
|
|
||||||
<view class="flex">
|
|
||||||
<view class="flex mr-[20rpx] flex-col justify-center items-center" @click="redirect({ url: '/addon/shop/pages/index', mode: 'reLaunch' })">
|
|
||||||
<view class="nc-iconfont nc-icon-shouyeV6xx11 text-[36rpx]"></view>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">{{t('index')}}</text>
|
|
||||||
</view>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<view>
|
|
||||||
<nc-contact
|
|
||||||
:send-message-title="sendMessageTitle"
|
|
||||||
:send-message-path="sendMessagePath"
|
|
||||||
:send-message-img="sendMessageImg">
|
|
||||||
<view class="flex flex-col justify-center items-center">
|
|
||||||
<text class="nc-iconfont nc-icon-kefuV6xx-1 text-[36rpx]"></text>
|
|
||||||
<text class="text-[20rpx] mt-[10rpx]">客服</text>
|
|
||||||
</view>
|
|
||||||
</nc-contact>
|
|
||||||
</view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="flex justify-end">
|
|
||||||
<view class="min-w-[180rpx] box-border text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#ccc] text-[#333] rounded-full ml-[20rpx]" @click="refundBtnFn('cancel')" v-if="['6','7','8','-1'].indexOf(detail.status) == -1">{{t('refundApply')}}</view>
|
|
||||||
<view v-if="['3'].indexOf(detail.status) != -1" class="min-w-[180rpx] box-border text-[#333] text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#ccc] rounded-full ml-[20rpx] px-[20rpx]" @click.stop="refundBtnFn('edit')" >编辑退款信息</view>
|
|
||||||
<view v-if="['2'].indexOf(detail.status) != -1" class="min-w-[180rpx] box-border text-[#333] text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#ccc] rounded-full ml-[20rpx] px-[20rpx]" @click.stop="refundBtnFn('logistics')">填写发货物流</view>
|
|
||||||
<view v-if="['5'].indexOf(detail.status) != -1" class="min-w-[180rpx] box-border text-[#333] text-[26rpx] h-[70rpx] flex-center border-[2rpx] border-solid border-[#ccc] rounded-full ml-[20rpx] px-[20rpx]" @click.stop="refundBtnFn('editLogistics')">编辑发货物流</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-else>
|
|
||||||
<view class="bg-linear">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
|
|
||||||
<!-- #endif -->
|
|
||||||
<view class="flex justify-between items-center pl-[40rpx] pr-[50rpx] h-[280rpx] box-border pb-[90rpx]">
|
|
||||||
<view class="text-[36rpx] font-500 leading-[42rpx] text-[#fff]">{{ detail.status_name }}</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<image class="w-[180rpx] h-[140rpx]" :src="img('addon/shop/detail/payment.png')" mode="aspectFit"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin card-template mt-[-79rpx] flex justify-between flex-wrap">
|
|
||||||
<view class="w-[150rpx] h-[150rpx] flex-2" @click="goodsEvent(detail.order_goods.goods_id)">
|
|
||||||
<u--image radius="var(--goods-rounded-big)" width="150rpx" height="150rpx" :src="img(detail.order_goods.sku_image ? detail.order_goods.sku_image.split(',')[0] : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
</view>
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
|
|
||||||
<view>
|
|
||||||
<view class="text-[28rpx] max-w-[490rpx] truncate leading-[40rpx]">{{ detail.order_goods.goods_name }}</view>
|
|
||||||
<view class="text-[24rpx] mt-[14rpx] text-[var(--text-color-light9)] truncate max-w-[490rpx] leading-[28rpx]" v-if="detail.order_goods.sku_name">
|
|
||||||
{{ detail.order_goods.sku_name }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-center leading-[28rpx]">
|
|
||||||
<view class="price-font">
|
|
||||||
<text class="text-[24rpx] font-500">¥</text>
|
|
||||||
<text class="text-[40rpx] font-500">{{ parseFloat(detail.order_goods.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[24rpx] font-500">.{{ parseFloat(detail.order_goods.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx]">x{{ detail.order_goods.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin card-template top-mar">
|
|
||||||
<view class="card-template-item justify-between text-[28rpx]">
|
|
||||||
<view>联系人</view>
|
|
||||||
<view>{{ detail.refund_address.contact_name }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item justify-between text-[28rpx]">
|
|
||||||
<view>手机号</view>
|
|
||||||
<view>{{ detail.refund_address.mobile }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="card-template-item justify-between text-[28rpx]">
|
|
||||||
<view>退货地址</view>
|
|
||||||
<view class="w-[460rpx] text-sm text-right" v-if="detail.refund_address">{{ detail.refund_address.full_address || '--' }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="sidebar-margin card-template top-mar py-[var(--top-m)]">
|
|
||||||
<view class="title">物流信息</view>
|
|
||||||
<u--form labelPosition="left" :model="formData" :rules="rules" errorType='toast' ref="deliveryForm" labelWidth="140rpx" :labelStyle="{'fontSize': '28rpx'}">
|
|
||||||
<u-form-item label="物流公司" prop="express_company" :borderBottom="false">
|
|
||||||
<u--input border="none" v-model="formData.express_company" placeholder="请输入物流公司" placeholderClass="text-sm !text-[var(--text-color-light9)]" fontSize="28rpx" maxlength="50"></u--input>
|
|
||||||
</u-form-item>
|
|
||||||
<view class="mt-[16rpx]">
|
|
||||||
<u-form-item label="物流单号" prop="express_number" :borderBottom="false">
|
|
||||||
<u--input border="none" placeholder="请输入物流单号" v-model="formData.express_number" placeholderClass="text-sm !text-[var(--text-color-light9)]" fontSize="28rpx" maxlength="100"></u--input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[16rpx]">
|
|
||||||
<u-form-item label="物流说明" :borderBottom="false">
|
|
||||||
<u--input border="none" placeholder="选填" v-model="formData.remark" placeholderClass="text-sm !text-[var(--text-color-light9)]" fontSize="28rpx" maxlength="100"></u--input>
|
|
||||||
</u-form-item>
|
|
||||||
</view>
|
|
||||||
</u--form>
|
|
||||||
</view>
|
|
||||||
<view class="common-tab-bar-placeholder"></view>
|
|
||||||
<view class="common-tab-bar fixed left-[var(--sidebar-m)] right-[var(--sidebar-m)] bottom-[0]">
|
|
||||||
<button class="mt-[80rpx] primary-btn-bg text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" @click="deliverySave">提交</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<logistics-tracking ref="materialRef"></logistics-tracking>
|
|
||||||
<u-modal :show="cancelRefundShow" confirmColor="var(--primary-color)" :content="t('cancelRefundContent')" :showCancelButton="true" :closeOnClickOverlay="true" @cancel="refundCancel" @confirm="refundConfirm"></u-modal>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, computed, nextTick } from 'vue';
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect, copy, goback } from '@/utils/common';
|
|
||||||
import { topTabar } from '@/utils/topTabbar'
|
|
||||||
import { getRefundDetail, refundDelivery, editRefundDelivery, closeRefund } from '@/addon/shop/api/refund';
|
|
||||||
import logisticsTracking from '@/addon/shop/pages/order/components/logistics-tracking/logistics-tracking.vue'
|
|
||||||
|
|
||||||
/********* 自定义头部 - start ***********/
|
|
||||||
const topTabarObj = topTabar()
|
|
||||||
let topTabbarData = topTabarObj.setTopTabbarParam({title:'退款详情'})
|
|
||||||
/********* 自定义头部 - end ***********/
|
|
||||||
|
|
||||||
const detail = ref<Object>({});
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
const orderRefundNo = ref('');
|
|
||||||
const type = ref('');
|
|
||||||
const isEditDelivery = ref(false);
|
|
||||||
|
|
||||||
const sendMessageTitle = ref('')
|
|
||||||
const sendMessagePath = ref('')
|
|
||||||
const sendMessageImg = ref('')
|
|
||||||
// 物流信息
|
|
||||||
const formData = ref({
|
|
||||||
express_number: '',
|
|
||||||
express_company: '',
|
|
||||||
remark: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
// 物流验证
|
|
||||||
const rules = computed(() => {
|
|
||||||
return {
|
|
||||||
'express_number': {
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
message: '请输入物流单号',
|
|
||||||
trigger: ['blur', 'change']
|
|
||||||
},
|
|
||||||
'express_company': {
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
message: '请输入物流公司',
|
|
||||||
trigger: ['blur', 'change']
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
orderRefundNo.value = option.order_refund_no;
|
|
||||||
if(orderRefundNo.value){
|
|
||||||
type.value = option.type;
|
|
||||||
isEditDelivery.value = option.is_edit_delivery;
|
|
||||||
|
|
||||||
refundDetailFn(orderRefundNo.value);
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/refund/list',
|
|
||||||
title: '缺少订单号'
|
|
||||||
};
|
|
||||||
goback(parameter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refundDetailFn = (refundNo: any) => {
|
|
||||||
loading.value = true;
|
|
||||||
getRefundDetail(refundNo).then((res: any) => {
|
|
||||||
detail.value = res.data;
|
|
||||||
// 赋值物流信息
|
|
||||||
if(isEditDelivery.value && detail.value.delivery){
|
|
||||||
formData.value.express_number = detail.value.delivery.express_number
|
|
||||||
formData.value.express_company = detail.value.delivery.express_company
|
|
||||||
formData.value.remark = detail.value.delivery.remark
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessageTitle.value = detail.value.order_goods.goods_name
|
|
||||||
sendMessageImg.value = img(detail.value.order_goods.goods_image_thumb_small || '')
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const goodsEvent = (id: number) => {
|
|
||||||
redirect({
|
|
||||||
url: '/addon/shop/pages/goods/detail',
|
|
||||||
param: {
|
|
||||||
goods_id: id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交物流信息
|
|
||||||
const deliveryForm = ref()
|
|
||||||
const deliverySave = ()=>{
|
|
||||||
deliveryForm.value.validate().then(res => {
|
|
||||||
let obj = {delivery: formData.value,order_refund_no: detail.value.order_refund_no}
|
|
||||||
let api = isEditDelivery.value ? editRefundDelivery(obj) : refundDelivery(obj);
|
|
||||||
api.then((res) => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/list' })
|
|
||||||
},500)
|
|
||||||
}).catch(() => {
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundBtnFn = (type:any) => {
|
|
||||||
if(type == 'cancel'){
|
|
||||||
currRefundOn = detail.value.order_refund_no;
|
|
||||||
cancelRefundShow.value = true;
|
|
||||||
}else if(type == 'edit'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/edit_apply', param: { order_refund_no : detail.value.order_refund_no } })
|
|
||||||
}else if(type == 'logistics'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : detail.value.order_refund_no, type: 'logistics' } })
|
|
||||||
}else if(type == 'editLogistics'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : detail.value.order_refund_no, type: 'logistics', is_edit_delivery: true } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 撤销维权
|
|
||||||
const cancelRefundShow = ref(false);
|
|
||||||
let currRefundOn = "";
|
|
||||||
|
|
||||||
const refundConfirm = ()=>{
|
|
||||||
closeRefund(currRefundOn).then((res) => {
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
refundDetailFn(orderRefundNo.value);
|
|
||||||
}).catch(() => {
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundCancel = ()=>{
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-item {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-linear {
|
|
||||||
background: linear-gradient( 94deg, #F84949 8%, #FF9A68 99%);
|
|
||||||
}
|
|
||||||
:deep(.u-form-item__body__left__content__label){
|
|
||||||
height: 40rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-form-item__body){
|
|
||||||
padding: 0 !important;
|
|
||||||
height: 40rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-form-item){
|
|
||||||
margin-bottom: 34rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<swiper :indicator-dots="false" :autoplay="false" :disable-touch="true" :current="step" class="h-screen" :duration="300" v-if="detail">
|
|
||||||
<swiper-item>
|
|
||||||
<scroll-view scroll-y="true" class="bg-page min-h-screen overflow-hidden">
|
|
||||||
<view class="m-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] py-[var(--pad-top-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="flex">
|
|
||||||
<u--image :radius="'var(--goods-rounded-small)'" width="120rpx" height="120rpx" :src="img(orderDetail.sku_image.split(',')[0])" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[120rpx] h-[120rpx]" :radius="'var(--goods-rounded-small)'" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="flex-1 w-0 ml-[20rpx]">
|
|
||||||
<view class="text-ellipsis text-[28rpx] leading-normal truncate">{{orderDetail.goods_name}}</view>
|
|
||||||
<view v-if="orderDetail.sku_name" class="mt-[6rpx] text-[24rpx] leading-[1.3] text-[var(--text-color-light9)] truncate">{{ orderDetail.sku_name }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)] flex items-center" @click="selectRefundType(1)">
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx]">仅退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]" v-if="orderDetail.goods_type == 'real'">未收到货,或与商家协商一致不用退货只退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]" v-else-if="orderDetail.goods_type == 'virtual'">与商家协商一致不用退货只退款</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[28rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
<view class="py-[var(--pad-top-m)] flex items-center border-0 !border-t !border-[#f5f5f5] border-solid" v-if="orderDetail.goods_type == 'real' && (!orderDetail.delivery_status || orderDetail.delivery_status != 'wait_delivery')" @click="selectRefundType(2)">
|
|
||||||
<view class="flex-1">
|
|
||||||
<view class="text-[30rpx]">退货退款</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] text-[var(--text-color-light9)]">已收到货,需退还收到的货物</view>
|
|
||||||
</view>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx text-[28rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</swiper-item>
|
|
||||||
<swiper-item>
|
|
||||||
<scroll-view scroll-y="true" class="bg-page min-h-screen overflow-hidden">
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)] flex justify-between items-center">
|
|
||||||
<view class="text-[28rpx]">退款原因</view>
|
|
||||||
<view class="flex ml-[auto] items-center h-[30rpx]" @click="refundCausePopup = true">
|
|
||||||
<text class="text-[26rpx] text-[var(--text-color-light9)] truncate max-w-[460rpx]">{{ formData.reason || '请选择' }}</text>
|
|
||||||
<text class="nc-iconfont nc-icon-youV6xx pt-[4rpx] text-[24rpx] text-[var(--text-color-light9)]"></text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)]">
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<view class="text-[28rpx] font-500">退款金额</view>
|
|
||||||
<view class="flex justify-end items-center text-[var(--price-text-color)] price-font">
|
|
||||||
<text class="font-500 text-[36rpx] leading-none">¥</text>
|
|
||||||
<text class="font-500 text-[36rpx] leading-none">{{ formData.apply_money }}</text>
|
|
||||||
<!-- <input type="digit" v-model.number="formData.apply_money" class="font-500 text-[36rpx] leading-none" :style="{ width: inputWidth(formData.apply_money) }" @blur="handleInput"> -->
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="text-right text-[24rpx] text-[var(--text-color-light9)] mt-[10rpx]">
|
|
||||||
<!-- <text>最多可退¥{{ refundMoney.refund_money }}</text> -->
|
|
||||||
<text v-if="refundMoney.is_refund_delivery === 1 && Number(refundMoney.refund_delivery_money) > 0" class="ml-[10rpx]">(包含运费¥{{ refundMoney.refund_delivery_money }})</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[var(--top-m)] sidebar-margin px-[var(--pad-sidebar-m)] rounded-[var(--rounded-big)] bg-white">
|
|
||||||
<view class="pt-[var(--pad-top-m)] pb-[14rpx]">
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="font-500">上传凭证</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)] ml-[10rpx]">选填</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[30rpx]">
|
|
||||||
<u-upload :fileList="voucherListPreview" @afterRead="afterRead" @delete="deletePic" multiple :maxCount="9"/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-[24rpx] sidebar-margin px-[24rpx] rounded-md bg-white">
|
|
||||||
<view class="py-[var(--pad-top-m)]">
|
|
||||||
<view class="text-[28rpx] flex items-center">
|
|
||||||
<text class="font-500">补充描述</text>
|
|
||||||
<text class="text-[24rpx] text-[var(--text-color-light9)] ml-[10rpx]">选填</text>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[30rpx] h-[200rpx]">
|
|
||||||
<textarea class="leading-[1.5] h-[100%] w-[100%] text-[28rpx]" v-model="formData.remark" cols="30" rows="5" placeholder="补充描述,有助于更好的处理售后问题" placeholder-class="text-[26rpx] text-[var(--text-color-light9)]"></textarea>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-full">
|
|
||||||
<view class="py-[var(--top-m)] px-[var(--sidebar-m)] box-border">
|
|
||||||
<button class="primary-btn-bg !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" :loading="operateLoading" @click="save">提交</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 退款原因 -->
|
|
||||||
<u-popup :show="refundCausePopup" @close="refundCausePopup = false" @open="open" :closeable="true">
|
|
||||||
<view class="popup-common" @touchmove.prevent.stop>
|
|
||||||
<view class="title">退款原因</view>
|
|
||||||
<scroll-view scroll-y="true" class="h-[450rpx] px-[30rpx] box-border">
|
|
||||||
<u-radio-group v-model="currReasonName" placement="column" iconPlacement="right">
|
|
||||||
<u-radio activeColor="var(--primary-color)" :labelSize="'30rpx'" labelColor="#333" :customStyle="{marginBottom: '34rpx'}" v-for="(item, index) in reason" :key="index" :label="item" :name="item"></u-radio>
|
|
||||||
</u-radio-group>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="btn-wrap">
|
|
||||||
<button class="primary-btn-bg btn" @click="refundCausePopupFn">确定</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
</scroll-view>
|
|
||||||
</swiper-item>
|
|
||||||
</swiper>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { redirect, img, moneyFormat, goback } from '@/utils/common'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { getRefundReason, editRefund, getRefundDetail,getRefundMoneyAgain } from '@/addon/shop/api/refund'
|
|
||||||
import { uploadImage } from '@/app/api/system'
|
|
||||||
|
|
||||||
const detail = ref(null)
|
|
||||||
const orderDetail = ref({})
|
|
||||||
const orderGoodsId = ref(0)
|
|
||||||
const step = ref(0)
|
|
||||||
const refundCausePopup = ref(false)
|
|
||||||
const formData = ref({
|
|
||||||
order_id: detail.value?.order_id,
|
|
||||||
order_goods_id: orderGoodsId.value,
|
|
||||||
order_refund_no:'',
|
|
||||||
refund_type: '',
|
|
||||||
apply_money: '',
|
|
||||||
reason: '',
|
|
||||||
remark: '',
|
|
||||||
voucher: []
|
|
||||||
})
|
|
||||||
const refundMoney = ref<any>({})
|
|
||||||
const reason = ref<string[]>([])
|
|
||||||
const currReasonName = ref('')
|
|
||||||
|
|
||||||
getRefundReason().then(({ data }) => {
|
|
||||||
reason.value = data
|
|
||||||
if(reason.value && reason.value.length) currReasonName.value = reason.value[0];
|
|
||||||
})
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
orderGoodsId.value = option.order_goods_id || 0
|
|
||||||
if(option.order_refund_no){
|
|
||||||
getRefundDetail(option.order_refund_no).then(({ data }) => {
|
|
||||||
detail.value = data
|
|
||||||
orderDetail.value = data.order_goods;
|
|
||||||
|
|
||||||
// 初始化信息
|
|
||||||
formData.value.order_goods_id = data.order_goods_id;
|
|
||||||
formData.value.order_id = data.order_id;
|
|
||||||
formData.value.order_refund_no = data.order_refund_no;
|
|
||||||
formData.value.remark = data.remark;
|
|
||||||
formData.value.reason = data.reason;
|
|
||||||
currReasonName.value = data.reason;
|
|
||||||
formData.value.voucher = data.voucher;
|
|
||||||
})
|
|
||||||
getRefundMoneyAgain({order_refund_no: option.order_refund_no}).then(res =>{
|
|
||||||
refundMoney.value = res.data
|
|
||||||
formData.value.apply_money = moneyFormat(refundMoney.value.refund_money)
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/refund/list',
|
|
||||||
title: '缺少订单号'
|
|
||||||
};
|
|
||||||
goback(parameter);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const inputWidth = computed((value) => {
|
|
||||||
return function (value) {
|
|
||||||
if (value == '' || value == 0) {
|
|
||||||
return '70rpx';
|
|
||||||
} else {
|
|
||||||
return String(value).length * 17 + 'rpx';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectRefundType = (type : number) => {
|
|
||||||
formData.value.refund_type = type
|
|
||||||
step.value = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
const voucherListPreview = computed(() => {
|
|
||||||
return formData.value.voucher.map(item => {
|
|
||||||
return {url: img(item)}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const afterRead = (event) => {
|
|
||||||
event.file.forEach(item => {
|
|
||||||
uploadImage({
|
|
||||||
filePath: item.url,
|
|
||||||
name: 'file'
|
|
||||||
}).then(res => {
|
|
||||||
if (formData.value.voucher.length < 9 ) {
|
|
||||||
formData.value.voucher.push(res.data.url)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const deletePic = (event)=> {
|
|
||||||
formData.value.voucher.splice(event.index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const operateLoading = ref(false)
|
|
||||||
const save = ()=> {
|
|
||||||
if (!formData.value.reason) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '请选择退款原因',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Number(formData.value.apply_money).toFixed(2)) < 0) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '退款金额不能为0,保留两位小数',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Number(formData.value.apply_money) > Number(refundMoney.value.refund_money)) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '退款金额不能大于可退款总额',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operateLoading.value) return
|
|
||||||
operateLoading.value = true
|
|
||||||
|
|
||||||
editRefund(formData.value).then((res) => {
|
|
||||||
operateLoading.value = false
|
|
||||||
setTimeout(() => {
|
|
||||||
redirect({ url: '/addon/shop/pages/order/detail', param: { order_id: formData.value.order_id } })
|
|
||||||
}, 1000)
|
|
||||||
}).catch(() => {
|
|
||||||
operateLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundCausePopupFn = ()=>{
|
|
||||||
formData.value.reason = currReasonName.value;
|
|
||||||
refundCausePopup.value = false;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
:deep(.u-upload__button) {
|
|
||||||
width: 70px !important;
|
|
||||||
height: 70px !important;
|
|
||||||
border: 1px dashed #ddd;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 20rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.u-upload__wrap__preview__image) {
|
|
||||||
width: 70px!important;
|
|
||||||
height: 70px!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" :style="themeColor()">
|
|
||||||
|
|
||||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getRefundListFn">
|
|
||||||
<view class="sidebar-margin pt-[var(--top-m)]" v-if="list.length">
|
|
||||||
<view class="mb-[var(--top-m)] card-template" v-for="(item,index) in list" :key="index">
|
|
||||||
<view @click="toLink(item)">
|
|
||||||
<view class="flex justify-between items-center">
|
|
||||||
<view class="text-[#303133] text-[26rpx] font-400 leading-[34rpx]">
|
|
||||||
<text>{{ t('orderNo') }}:</text>
|
|
||||||
<text class="ml-[10rpx]">{{ item.order_refund_no }}</text>
|
|
||||||
<text class="text-[#303133] text-[24rpx] font-400 nc-iconfont nc-icon-fuzhiV6xx1 ml-[11rpx]" @click.stop="copy(item.order_refund_no)"></text>
|
|
||||||
</view>
|
|
||||||
<view class="text-[26rpx] leading-[34rpx] !text-[var(--primary-color)]">{{item.refund_type_name}}</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex mt-[20rpx]">
|
|
||||||
<u--image width="150rpx" height="150rpx" :radius="'var(--goods-rounded-big)'" :src="img(item.order_goods.goods_image_thumb_small ? item.order_goods.goods_image_thumb_small : '')" model="aspectFill">
|
|
||||||
<template #error>
|
|
||||||
<image class="w-[150rpx] h-[150rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
|
||||||
</template>
|
|
||||||
</u--image>
|
|
||||||
<view class="ml-[20rpx] flex flex-1 flex-col box-border">
|
|
||||||
<view class="flex justify-between items-baseline">
|
|
||||||
<view class="text-[28rpx] leading-[40rpx] text-[#303133] max-w-[322rpx] truncate font-400">{{ item.order_goods.goods_name }}</view>
|
|
||||||
<view class="text-right leading-[42rpx] ml-[10rpx]">
|
|
||||||
<text class="text-[22rpx] price-font">¥</text>
|
|
||||||
<text class="text-[36rpx] font-500 price-font">{{parseFloat(item.order_goods.price).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500 price-font">.{{parseFloat(item.order_goods.price).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-between items-baseline mt-[14rpx]">
|
|
||||||
<view class="flex flex-col">
|
|
||||||
<view class="text-[26rpx] truncate text-[var(--text-color-light6)] leading-[36rpx] max-w-[369rpx] mb-[10rpx]" v-if="item.order_goods.sku_name">{{ item.order_goods.sku_name }}</view>
|
|
||||||
<view class="text-[26rpx] font-400 leading-[36rpx] text-[var(--text-color-light6)]">退款状态:{{ item.status_name }}</view>
|
|
||||||
</view>
|
|
||||||
<text class="text-right text-[26rpx] font-400 w-[90rpx] leading-[36rpx]">x{{ item.order_goods.num }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex justify-end items-baseline mt-[20rpx]">
|
|
||||||
<view class="flex items-center">
|
|
||||||
<text class="text-[22rpx] leading-[30rpx] font-400 mr-[4rpx]">{{ t('refundMoney') }}:</text>
|
|
||||||
<view class="price-font leading-[42rpx] text-[var(--price-text-color)]">
|
|
||||||
<text class="text-[22rpx]">¥</text>
|
|
||||||
<template v-if="item.status == 8">
|
|
||||||
<text class="text-[36rpx] font-500">{{ parseFloat(item.money).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500">.{{ parseFloat(item.money).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<text class="text-[36rpx] font-500">{{ parseFloat(item.apply_money).toFixed(2).split('.')[0] }}</text>
|
|
||||||
<text class="text-[22rpx] font-500">.{{ parseFloat(item.apply_money).toFixed(2).split('.')[1] }}</text>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-[20rpx] flex flex-wrap justify-end" v-if="['6','7','8','-1','3','2','5'].indexOf(item.status) == -1">
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light6)] font-500 h-[56rpx] leading-[52rpx] box-border px-[23rpx] border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx]" @click.stop="refundBtnFn(item,'cancel')" v-if="['6','7','8','-1'].indexOf(item.status) == -1">{{t('refundApply')}}</view>
|
|
||||||
<view v-if="['3'].indexOf(item.status) != -1" class="text-[24rpx] font-500 text-[var(--text-color-light6)] h-[56rpx] box-border leading-[52rpx] px-[23rpx] border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx]" @click.stop="refundBtnFn(item,'edit')" >编辑退款信息</view>
|
|
||||||
<view v-if="['2'].indexOf(item.status) != -1" class=" text-[24rpx] font-500 text-[var(--text-color-light6)] h-[56rpx] box-border leading-[52rpx] px-[23rpx] border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx]" @click.stop="refundBtnFn(item,'logistics')">填写发货物流</view>
|
|
||||||
<view v-if="['5'].indexOf(item.status) != -1" class="text-[24rpx] font-500 text-[var(--text-color-light6)] h-[56rpx] box-border leading-[52rpx] px-[23rpx] border-[2rpx] border-solid border-[var(--text-color-light9)] rounded-full ml-[20rpx]" @click.stop="refundBtnFn(item,'editLogistics')">编辑发货物流</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<mescroll-empty :option="{tip : '暂无订单'}" v-if="!list.length && loading"></mescroll-empty>
|
|
||||||
|
|
||||||
</mescroll-body>
|
|
||||||
<u-modal :show="cancelRefundShow" confirmColor="var(--primary-color)" :content="t('cancelRefundContent')" :showCancelButton="true" :closeOnClickOverlay="true" @cancel="refundCancel" @confirm="refundConfirm"></u-modal>
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<!-- 小程序隐私协议 -->
|
|
||||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref,nextTick } from 'vue';
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect,copy } from '@/utils/common'
|
|
||||||
import { getRefundList, closeRefund } from '@/addon/shop/api/refund';
|
|
||||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
||||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
||||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
||||||
import { onLoad,onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
|
|
||||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
||||||
const list = ref<Array<Object>>([]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const cancelRefundShow = ref(false);
|
|
||||||
|
|
||||||
const wxPrivacyPopupRef:any = ref(null)
|
|
||||||
|
|
||||||
onLoad(()=>{
|
|
||||||
// #ifdef MP
|
|
||||||
nextTick(()=>{
|
|
||||||
if(wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
|
|
||||||
const getRefundListFn = (mescroll) => {
|
|
||||||
loading.value = false;
|
|
||||||
let data : object = {
|
|
||||||
page: mescroll.num,
|
|
||||||
limit: mescroll.size
|
|
||||||
};
|
|
||||||
|
|
||||||
getRefundList(data).then((res) => {
|
|
||||||
let newArr = (res.data.data as Array<Object>);
|
|
||||||
//设置列表数据
|
|
||||||
if (mescroll.num == 1) {
|
|
||||||
list.value = []; //如果是第一页需手动制空列表
|
|
||||||
}
|
|
||||||
list.value = list.value.concat(newArr);
|
|
||||||
mescroll.endSuccess(newArr.length);
|
|
||||||
loading.value = true;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = true;
|
|
||||||
mescroll.endErr(); // 请求失败, 结束加载
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const toLink = (data) => {
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : data.order_refund_no } })
|
|
||||||
}
|
|
||||||
|
|
||||||
let currRefundOn = "";
|
|
||||||
const refundBtnFn = (data, type) => {
|
|
||||||
if(type == 'cancel'){
|
|
||||||
currRefundOn = data.order_refund_no;
|
|
||||||
cancelRefundShow.value = true;
|
|
||||||
}else if(type == 'edit'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/edit_apply', param: { order_refund_no : data.order_refund_no } })
|
|
||||||
}else if(type == 'logistics'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : data.order_refund_no, type: 'logistics' } })
|
|
||||||
}else if(type == 'editLogistics'){
|
|
||||||
redirect({ url: '/addon/shop/pages/refund/detail', param: { order_refund_no : data.order_refund_no, type: 'logistics', is_edit_delivery: true } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundConfirm = ()=>{
|
|
||||||
closeRefund(currRefundOn).then((res) => {
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
getMescroll().resetUpScroll();
|
|
||||||
}).catch(() => {
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const refundCancel = ()=>{
|
|
||||||
cancelRefundShow.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-item {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view :style="themeColor()">
|
|
||||||
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="!loading">
|
|
||||||
<view class="pt-[var(--top-m)]">
|
|
||||||
<view class="card-template sidebar-margin mb-[var(--top-m)]" v-for="(item,index) in detail.refund_log">
|
|
||||||
<view class="text-[28rpx]">{{item.type_name || '--'}}</view>
|
|
||||||
<view class="text-[24rpx] mt-[20rpx] mb-[10rpx] text-[var(--text-color-light9)]">{{item.main_type_name}} {{item.main_name}}</view>
|
|
||||||
<view class="text-[24rpx] text-[var(--text-color-light9)]">{{item.create_time}}</view>
|
|
||||||
</view>
|
|
||||||
<view class="w-full footer">
|
|
||||||
<view class="py-[var(--top-m)] px-[var(--sidebar-m)] footer w-full fixed bottom-0 left-0 right-0 box-border">
|
|
||||||
<button class="primary-btn-bg text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] mx-0 flex-1 font-500" @click="redirect({url: '/addon/shop/pages/refund/detail', param: { order_refund_no: orderRefundNo }})">返回详情</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<loading-page :loading="loading"></loading-page>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, reactive, computed } from 'vue';
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { img, redirect, goback } from '@/utils/common';
|
|
||||||
import { getRefundDetail } from '@/addon/shop/api/refund';
|
|
||||||
|
|
||||||
const detail = ref<Object>({});
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
const orderRefundNo = ref('')
|
|
||||||
|
|
||||||
onLoad((option: any) => {
|
|
||||||
orderRefundNo.value = option.order_refund_no;
|
|
||||||
if(option.order_refund_no){
|
|
||||||
refundDetailFn(option.order_refund_no);
|
|
||||||
}else{
|
|
||||||
let parameter = {
|
|
||||||
url:'/addon/shop/pages/refund/list',
|
|
||||||
title: '缺少订单号'
|
|
||||||
};
|
|
||||||
goback(parameter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const refundDetailFn = (refundNo: any) => {
|
|
||||||
loading.value = true;
|
|
||||||
getRefundDetail(refundNo).then((res: any) => {
|
|
||||||
detail.value = res.data;
|
|
||||||
loading.value = false;
|
|
||||||
}).catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.footer{
|
|
||||||
height: calc(80rpx + var(--top-m) + var(--top-m) + constant(safe-area-inset-bottom)) !important;
|
|
||||||
height: calc(80rpx + var(--top-m) + var(--top-m) + env(safe-area-inset-bottom)) !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
import { defineStore } from 'pinia'
|
|
||||||
import { t } from '@/locale'
|
|
||||||
import { redirect, getToken } from '@/utils/common'
|
|
||||||
import { addCart, editCart, deleteCart, clearCart, getCartList, getCartSum } from '@/addon/shop/api/cart';
|
|
||||||
|
|
||||||
interface Cart {
|
|
||||||
cartList: AnyObject
|
|
||||||
totalNum: number
|
|
||||||
totalMoney: number
|
|
||||||
isRepeat: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const useCartStore = defineStore('cart', {
|
|
||||||
state: (): Cart => {
|
|
||||||
return {
|
|
||||||
cartList: {}, // 购物车列表
|
|
||||||
totalNum: 0, // 购物车商品总数量
|
|
||||||
totalMoney: 0, // 购物车商品总价格
|
|
||||||
isRepeat: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
// 查询购物车列表
|
|
||||||
getList(callback: any = null) {
|
|
||||||
if (!getToken()) {
|
|
||||||
// 每次查询清空
|
|
||||||
for (let k in this.cartList) {
|
|
||||||
delete this.cartList[k];
|
|
||||||
}
|
|
||||||
this.totalNum = 0;
|
|
||||||
this.totalMoney = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getCartList({}).then((res: any) => {
|
|
||||||
let data = res.data;
|
|
||||||
|
|
||||||
// 每次查询清空
|
|
||||||
for (let k in this.cartList) {
|
|
||||||
delete this.cartList[k];
|
|
||||||
}
|
|
||||||
if (data) {
|
|
||||||
data.forEach((item: any) => {
|
|
||||||
if (item.goods.status == 1 && item.goods.delete_time == 0 && item.goodsSku) {
|
|
||||||
let cart: any = {
|
|
||||||
id: item.id,
|
|
||||||
goods_id: item.goods_id,
|
|
||||||
sku_id: item.sku_id,
|
|
||||||
stock: item.goodsSku.stock,
|
|
||||||
num: item.num,
|
|
||||||
sale_price: item.goodsSku.price
|
|
||||||
};
|
|
||||||
|
|
||||||
if (item.goods.member_discount && getToken() && item.goodsSku.member_price != item.goodsSku.price) {
|
|
||||||
cart.sale_price = item.goodsSku.member_price ? item.goodsSku.member_price : item.goodsSku.price // 会员价
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo sale_price 改成 price
|
|
||||||
|
|
||||||
if (!this.cartList['goods_' + cart.goods_id]) {
|
|
||||||
this.cartList['goods_' + cart.goods_id] = {};
|
|
||||||
}
|
|
||||||
this.cartList['goods_' + cart.goods_id]['sku_' + cart.sku_id] = cart;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.calculateNum();
|
|
||||||
if (callback && typeof callback == 'function') callback();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 购物车数量增加
|
|
||||||
* data:数据源
|
|
||||||
* step:记步数量,默认为:1,每次加一个,设置为:0时,按照 num 修改
|
|
||||||
*/
|
|
||||||
increase(data: any, step = 1, callback: any = null) {
|
|
||||||
if (!data || (data && Object.keys(data).length == 0) || !data.goods_id || !data.sku_id) return;
|
|
||||||
if (!getToken()) return;
|
|
||||||
|
|
||||||
let num = data.num || 0; // 当前数量
|
|
||||||
let updateNum = num + step; // 变更数量
|
|
||||||
|
|
||||||
let api = data.id ? editCart : addCart;
|
|
||||||
|
|
||||||
if (updateNum > parseInt(data.stock)) {
|
|
||||||
uni.showToast({ title: '商品库存不足', icon: 'none' })
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isRepeat) return;
|
|
||||||
this.isRepeat = true;
|
|
||||||
|
|
||||||
// 更新存储数据
|
|
||||||
if (data.id) {
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = updateNum;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// 如果商品第一次添加,则初始化数据
|
|
||||||
if (!this.cartList['goods_' + data.goods_id]) {
|
|
||||||
this.cartList['goods_' + data.goods_id] = {};
|
|
||||||
}
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] = {
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
stock: data.stock,
|
|
||||||
num: updateNum,
|
|
||||||
sale_price: data.sale_price
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.calculateNum();
|
|
||||||
|
|
||||||
api({
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
num: updateNum
|
|
||||||
}).then(res => {
|
|
||||||
this.getList(callback)
|
|
||||||
this.isRepeat = false;
|
|
||||||
}).catch(res => {
|
|
||||||
this.isRepeat = false;
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 购物车数量减少
|
|
||||||
* data:数据源
|
|
||||||
* step:记步数量,默认为:1,每次减一个,设置为:0时,按照 num 修改
|
|
||||||
*/
|
|
||||||
reduce(data: any, step = 1, callback: any = null) {
|
|
||||||
if (!data || (data && Object.keys(data).length == 0) || !data.goods_id || !data.sku_id) return;
|
|
||||||
if (!getToken()) return;
|
|
||||||
|
|
||||||
let num = data.num || 0; // 当前数量
|
|
||||||
let updateNum = num - step; // 变更数量
|
|
||||||
|
|
||||||
let api = updateNum > 0 ? editCart : deleteCart;
|
|
||||||
|
|
||||||
if (this.isRepeat) return;
|
|
||||||
this.isRepeat = true;
|
|
||||||
|
|
||||||
// 更新存储数据
|
|
||||||
if (updateNum > 0) {
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = updateNum;
|
|
||||||
} else {
|
|
||||||
delete this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id];
|
|
||||||
if (Object.keys(this.cartList['goods_' + data.goods_id]).length == 0) delete this.cartList['goods_' + data.goods_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.calculateNum();
|
|
||||||
|
|
||||||
api({
|
|
||||||
ids: data.id, // 删除接口用
|
|
||||||
id: data.id,
|
|
||||||
goods_id: data.goods_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
num: updateNum
|
|
||||||
}).then(res => {
|
|
||||||
this.getList(callback);
|
|
||||||
this.isRepeat = false;
|
|
||||||
}).catch(res => {
|
|
||||||
this.isRepeat = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 购物车删除
|
|
||||||
delete(ids: any, callback: any = null) {
|
|
||||||
if (!ids) return;
|
|
||||||
|
|
||||||
deleteCart({
|
|
||||||
ids
|
|
||||||
}).then(res => {
|
|
||||||
this.getList();
|
|
||||||
this.isRepeat = false;
|
|
||||||
if (callback) callback();
|
|
||||||
}).catch(res => {
|
|
||||||
this.isRepeat = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算购物车商品的总数量、总价格
|
|
||||||
calculateNum() {
|
|
||||||
this.totalNum = 0;
|
|
||||||
this.totalMoney = 0;
|
|
||||||
|
|
||||||
if (Object.keys(this.cartList).length) {
|
|
||||||
for (let goods in this.cartList) {
|
|
||||||
let totalNum = 0;
|
|
||||||
let totalMoney = 0;
|
|
||||||
for (let sku in this.cartList[goods]) {
|
|
||||||
if (typeof this.cartList[goods][sku] == 'object') {
|
|
||||||
totalNum += this.cartList[goods][sku].num;
|
|
||||||
totalMoney += this.cartList[goods][sku].num * this.cartList[goods][sku].sale_price;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.cartList[goods].totalNum = totalNum;
|
|
||||||
this.cartList[goods].totalMoney = totalMoney.toFixed(2);
|
|
||||||
|
|
||||||
this.totalNum += totalNum;
|
|
||||||
this.totalMoney += totalMoney;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.totalMoney = this.totalMoney.toFixed(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default useCartStore
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
.remove-border {
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************** 商品列表 state **********************/
|
|
||||||
.brand-tag{
|
|
||||||
position: relative;
|
|
||||||
top: -2rpx;
|
|
||||||
display: inline;
|
|
||||||
line-height: 38rpx;
|
|
||||||
padding: 4rpx 8rpx;
|
|
||||||
border-radius: 4rpx;
|
|
||||||
margin-right: 8rpx;
|
|
||||||
background: red;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-size: 18rpx;
|
|
||||||
color: #fff;
|
|
||||||
&.middle{
|
|
||||||
padding: 4rpx 8rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
font-size: 20rpx;
|
|
||||||
margin-right: 6rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.base-tag {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 34rpx;
|
|
||||||
font-size: 18rpx;
|
|
||||||
padding: 0 8rpx;
|
|
||||||
color: #333;
|
|
||||||
border-radius: 4rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
margin-right: 8rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-top: 8rpx;
|
|
||||||
border: 2rpx solid transparent;
|
|
||||||
&.middle{
|
|
||||||
height: 40rpx;
|
|
||||||
padding: 0 12rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
font-size: 20rpx;
|
|
||||||
margin-right: 16rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-tag {
|
|
||||||
display: block;
|
|
||||||
height: 34rpx;
|
|
||||||
width: auto;
|
|
||||||
border-radius: 4rpx;
|
|
||||||
margin-right: 14rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-top: 8rpx;
|
|
||||||
&.middle{
|
|
||||||
height: 38rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
margin-right: 16rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/******************** 商品列表 end **********************/
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import TransformCoordinate from './transformCoordinate.js'
|
|
||||||
import useConfigStore from "@/stores/config";
|
|
||||||
|
|
||||||
function openMapByDefault(latitude, longitude, name) {
|
|
||||||
uni.openLocation({
|
|
||||||
latitude: latitude,
|
|
||||||
longitude: longitude,
|
|
||||||
name: name,
|
|
||||||
fail: (e) => {
|
|
||||||
uni.showModal({
|
|
||||||
content: '打开地图失败,请稍后重试',
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function openMapByAndroid(latitude, longitude, name) {
|
|
||||||
let url = ''; // 回调地址
|
|
||||||
let identity = ''; // 程序名称
|
|
||||||
if (plus.runtime.isApplicationExist({
|
|
||||||
pname: 'com.baidu.BaiduMap'
|
|
||||||
})) { // baidumap
|
|
||||||
url = `baidumap://map/marker?location=${latitude},${longitude}&title=${name}&coord_type=gcj02&src=andr.baidu.openAPIdemo`
|
|
||||||
identity = 'com.baidu.BaiduMap'
|
|
||||||
openURL(url, identity)
|
|
||||||
} else if (plus.runtime.isApplicationExist({
|
|
||||||
pname: 'com.autonavi.minimap'
|
|
||||||
})) { // 高德
|
|
||||||
url = `androidamap://viewMap?sourceApplication=appname&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
|
|
||||||
identity = 'com.autonavi.minimap'
|
|
||||||
openURL(url, identity)
|
|
||||||
} else {
|
|
||||||
openMapByDefault(latitude, longitude, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openMapByIos(latitude, longitude, name) {
|
|
||||||
let url = ''; // 回调地址
|
|
||||||
let errorCB = ''; // url失败的回调地址
|
|
||||||
let identity = ''; // 程序名称
|
|
||||||
|
|
||||||
if (plus.runtime.isApplicationExist({
|
|
||||||
action: 'baidumap://'
|
|
||||||
})) { // baidumap
|
|
||||||
url =
|
|
||||||
`baidumap://map/marker?location=${latitude},${longitude}&title=${name}&content=${name}&src=ios.baidu.openAPIdemo&coord_type=gcj02`;
|
|
||||||
openURL(url, identity)
|
|
||||||
} else if (plus.runtime.isApplicationExist({
|
|
||||||
action: 'iosamap://'
|
|
||||||
})) { // 高德
|
|
||||||
url = `iosamap://viewMap?sourceApplication=applicationName&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
|
|
||||||
openURL(url, identity)
|
|
||||||
} else {
|
|
||||||
openMapByDefault(latitude, longitude, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openURL(url, identity) {
|
|
||||||
let newurl = encodeURI(url);
|
|
||||||
plus.runtime.openURL(newurl, function(res) {
|
|
||||||
uni.showModal({
|
|
||||||
content: res.message,
|
|
||||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
|
||||||
})
|
|
||||||
}, identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCoordByType(longitude, latitude, coord_type) {
|
|
||||||
switch (coord_type) {
|
|
||||||
case 'gcj02':
|
|
||||||
return [longitude, latitude]
|
|
||||||
break;
|
|
||||||
case 'bd09':
|
|
||||||
return TransformCoordinate.bd09togcj02(longitude, latitude)
|
|
||||||
break;
|
|
||||||
case 'wgs84':
|
|
||||||
return TransformCoordinate.wgs84togcj02(longitude, latitude)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return [longitude, latitude]
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default {
|
|
||||||
/* 打开地图 */
|
|
||||||
openMap(latitude, longitude, name, coord_type = 'gcj02') {
|
|
||||||
let arr = getCoordByType(longitude, latitude, coord_type)
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
switch (uni.getSystemInfoSync().platform) {
|
|
||||||
case 'android':
|
|
||||||
// console.log('运行Android上')
|
|
||||||
openMapByAndroid(arr[1], arr[0], name)
|
|
||||||
break;
|
|
||||||
case 'ios':
|
|
||||||
// console.log('运行iOS上')
|
|
||||||
openMapByIos(arr[1], arr[0], name)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
openMapByDefault(arr[1], arr[0], name)
|
|
||||||
// console.log('运行在开发者工具上')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
openMapByDefault(arr[1], arr[0], name)
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
/**
|
|
||||||
* Created by Wandergis on 2015/7/8.
|
|
||||||
* 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
|
|
||||||
*/
|
|
||||||
|
|
||||||
//定义一些常量
|
|
||||||
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
|
|
||||||
var PI = 3.1415926535897932384626;
|
|
||||||
var a = 6378245.0;
|
|
||||||
var ee = 0.00669342162296594323;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
|
|
||||||
* 即 百度 转 谷歌、高德
|
|
||||||
* @param bd_lon
|
|
||||||
* @param bd_lat
|
|
||||||
* @returns {*[]}
|
|
||||||
*/
|
|
||||||
function bd09togcj02(bd_lon, bd_lat) {
|
|
||||||
var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
|
|
||||||
var x = bd_lon - 0.0065;
|
|
||||||
var y = bd_lat - 0.006;
|
|
||||||
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
|
|
||||||
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
|
|
||||||
var gg_lng = z * Math.cos(theta);
|
|
||||||
var gg_lat = z * Math.sin(theta);
|
|
||||||
return [gg_lng, gg_lat]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
|
|
||||||
* 即谷歌、高德 转 百度
|
|
||||||
* @param lng
|
|
||||||
* @param lat
|
|
||||||
* @returns {*[]}
|
|
||||||
*/
|
|
||||||
function gcj02tobd09(lng, lat) {
|
|
||||||
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
|
|
||||||
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
|
|
||||||
var bd_lng = z * Math.cos(theta) + 0.0065;
|
|
||||||
var bd_lat = z * Math.sin(theta) + 0.006;
|
|
||||||
return [bd_lng, bd_lat]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WGS84转GCj02
|
|
||||||
* @param lng
|
|
||||||
* @param lat
|
|
||||||
* @returns {*[]}
|
|
||||||
*/
|
|
||||||
function wgs84togcj02(lng, lat) {
|
|
||||||
if (out_of_china(lng, lat)) {
|
|
||||||
return [lng, lat]
|
|
||||||
} else {
|
|
||||||
var dlat = transformlat(lng - 105.0, lat - 35.0);
|
|
||||||
var dlng = transformlng(lng - 105.0, lat - 35.0);
|
|
||||||
var radlat = lat / 180.0 * PI;
|
|
||||||
var magic = Math.sin(radlat);
|
|
||||||
magic = 1 - ee * magic * magic;
|
|
||||||
var sqrtmagic = Math.sqrt(magic);
|
|
||||||
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
|
|
||||||
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
|
|
||||||
var mglat = lat + dlat;
|
|
||||||
var mglng = lng + dlng;
|
|
||||||
return [mglng, mglat]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GCJ02 转换为 WGS84
|
|
||||||
* @param lng
|
|
||||||
* @param lat
|
|
||||||
* @returns {*[]}
|
|
||||||
*/
|
|
||||||
function gcj02towgs84(lng, lat) {
|
|
||||||
if (out_of_china(lng, lat)) {
|
|
||||||
return [lng, lat]
|
|
||||||
} else {
|
|
||||||
var dlat = transformlat(lng - 105.0, lat - 35.0);
|
|
||||||
var dlng = transformlng(lng - 105.0, lat - 35.0);
|
|
||||||
var radlat = lat / 180.0 * PI;
|
|
||||||
var magic = Math.sin(radlat);
|
|
||||||
magic = 1 - ee * magic * magic;
|
|
||||||
var sqrtmagic = Math.sqrt(magic);
|
|
||||||
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
|
|
||||||
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
|
|
||||||
mglat = lat + dlat;
|
|
||||||
mglng = lng + dlng;
|
|
||||||
return [lng * 2 - mglng, lat * 2 - mglat]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformlat(lng, lat) {
|
|
||||||
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
|
||||||
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
|
||||||
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
|
|
||||||
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformlng(lng, lat) {
|
|
||||||
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
|
||||||
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
|
||||||
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
|
|
||||||
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否在国内,不在国内则不做偏移
|
|
||||||
* @param lng
|
|
||||||
* @param lat
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function out_of_china(lng, lat) {
|
|
||||||
return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bd09togcj02: bd09togcj02, // 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
|
|
||||||
gcj02tobd09: gcj02tobd09, // 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
|
|
||||||
wgs84togcj02: wgs84togcj02, //
|
|
||||||
gcj02towgs84: gcj02towgs84,
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"--primary-color": "#FF4142",
|
|
||||||
"--primary-help-color": "#FB7939",
|
|
||||||
"--primary-color-dark": "#F26F3E",
|
|
||||||
"--primary-color-disabled": "#FFB397",
|
|
||||||
"--primary-color-light": "#FFEAEA",
|
|
||||||
"--primary-color-light2": "rgba(255,65,66,.04)",
|
|
||||||
"--page-bg-color": "#f6f6f6",
|
|
||||||
"--price-text-color": "#FF4142"
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
Reference in New Issue
Block a user