mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-08-06 10:57:25 +08:00
fix: 更新多个组件样式和功能以提升用户体验
- 在 myCollect.vue 中优化收藏页面的布局和样式,增加主题支持 - 在 searchPage.vue 中修复搜索组件的输入值设置逻辑 - 在 coupon/index.vue 中重构优惠券列表的展示逻辑,提升可用性 - 在 m-search-revision.vue 中调整搜索组件的样式和功能,增加清除图标的交互 - 在 pages.json 中禁用下拉刷新功能以改善性能
This commit is contained in:
@@ -1,17 +1,23 @@
|
||||
<template>
|
||||
<view class="serach">
|
||||
<view class="left-box" @tap="onClickLeft">
|
||||
<u-icon name="arrow-left" size="28" color="#666"></u-icon>
|
||||
<u-icon name="arrow-left" size="28rpx" color="#606266"></u-icon>
|
||||
</view>
|
||||
<view class="content" :style="{ 'border-radius': radius + 'px' }">
|
||||
<!-- HM修改 增加进入输入状态的点击范围 -->
|
||||
<view class="content-box" :class="{ center: mode === 2 }">
|
||||
<u-icon name="search" size="32" style="padding:0 15rpx;"></u-icon>
|
||||
<u-icon name="search" size="30rpx" color="#909399" style="padding:0 14rpx;"></u-icon>
|
||||
<!-- HM修改 增加placeholder input confirm-type confirm-->
|
||||
<input style="width:100%; " :placeholder="placeholder" placeholder-class="placeholder-color"
|
||||
@input="inputChange" confirm-type="search" @confirm="triggerConfirm" class="input"
|
||||
:class="{ center: !active && mode === 2 }" :focus="isFocus" v-model="inputVal" @focus="focus" @blur="blur" />
|
||||
<u-icon name="close" v-if="showClear && isDelShow" style="padding:0 30rpx;" @click="clear"></u-icon>
|
||||
<view
|
||||
class="clear-icon"
|
||||
v-if="showClear && isDelShow"
|
||||
@tap.stop.prevent="clear"
|
||||
>
|
||||
<u-icon name="close" size="28rpx" color="#909399"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
@@ -21,8 +27,8 @@
|
||||
</view>
|
||||
|
||||
<view v-else class="button-item">
|
||||
<u-icon name="grid-fill" size="32" @click="handelListClass()" v-if="!switchLayout"></u-icon>
|
||||
<u-icon v-else @click="handelListClass()" name="list-dot" size="32"></u-icon>
|
||||
<u-icon name="grid-fill" size="32rpx" color="var(--theme-light, #ff6b35)" @click="handelListClass()" v-if="!switchLayout"></u-icon>
|
||||
<u-icon v-else @click="handelListClass()" name="list-dot" size="32rpx" color="var(--theme-light, #ff6b35)"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -34,6 +40,7 @@ import { ref, watch, onMounted } from 'vue'
|
||||
const props = withDefaults(defineProps<{
|
||||
mode?: number
|
||||
placeholder?: string
|
||||
modelValue?: string
|
||||
value?: string
|
||||
radius?: string
|
||||
isFocusVal?: boolean
|
||||
@@ -41,13 +48,14 @@ const props = withDefaults(defineProps<{
|
||||
}>(), {
|
||||
mode: 1,
|
||||
placeholder: "请输入搜索内容",
|
||||
modelValue: "",
|
||||
value: "",
|
||||
radius: "60",
|
||||
isFocusVal: true,
|
||||
showClear: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['confirm', 'input', 'search', 'SwitchType'])
|
||||
const emit = defineEmits(['confirm', 'input', 'update:modelValue', 'search', 'SwitchType'])
|
||||
|
||||
const isShowSeachGoods = ref(false)
|
||||
const active = ref(false)
|
||||
@@ -58,6 +66,7 @@ const switchLayout = ref(true)
|
||||
|
||||
onMounted(() => {
|
||||
isFocus.value = props.isFocusVal
|
||||
inputVal.value = props.modelValue || props.value || ''
|
||||
})
|
||||
|
||||
//
|
||||
@@ -80,6 +89,7 @@ const triggerConfirm = () => {
|
||||
const inputChange = (event: any) => {
|
||||
var keyword = event.detail.value
|
||||
emit("input", keyword)
|
||||
emit("update:modelValue", keyword)
|
||||
if (inputVal.value) {
|
||||
isDelShow.value = true
|
||||
}
|
||||
@@ -103,11 +113,19 @@ const clear = () => {
|
||||
isFocus.value = false
|
||||
inputVal.value = ""
|
||||
active.value = false
|
||||
isDelShow.value = false
|
||||
//HM修改 清空内容时候触发组件input
|
||||
emit("input", "")
|
||||
emit("update:modelValue", "")
|
||||
//this.$emit('search', '');//HM修改 清空内容时候不进行搜索
|
||||
}
|
||||
|
||||
const setInputValue = (value: string) => {
|
||||
inputVal.value = value || ''
|
||||
emit("input", inputVal.value)
|
||||
emit("update:modelValue", inputVal.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回退到上一级
|
||||
*/
|
||||
@@ -144,6 +162,19 @@ const search = () => {
|
||||
watch(inputVal, (newVal) => {
|
||||
newVal ? (isDelShow.value = true) : (isDelShow.value = false)
|
||||
})
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal !== inputVal.value) {
|
||||
inputVal.value = newVal || ''
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
isShowSeachGoods,
|
||||
inputVal,
|
||||
clear,
|
||||
setInputValue,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -195,6 +226,15 @@ watch(inputVal, (newVal) => {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 72rpx;
|
||||
height: 70rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
"path": "myCollect",
|
||||
"style": {
|
||||
"navigationBarTitleText": "收藏",
|
||||
"enablePullDownRefresh": true, //下拉刷新
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom",
|
||||
"app-plus": {
|
||||
"scrollIndicator": "none"
|
||||
|
||||
@@ -1,84 +1,109 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<u-tabs
|
||||
class="coupon-tabs"
|
||||
:list="list"
|
||||
:scrollable="false"
|
||||
:lineColor="lightColor"
|
||||
:activeStyle="{ color: lightColor }"
|
||||
v-model:current="current"
|
||||
>
|
||||
</u-tabs>
|
||||
|
||||
<div class="empty" v-if="couponsList.length <= 0">
|
||||
<u-empty text="暂无优惠券" mode="coupon"></u-empty>
|
||||
</div>
|
||||
<view class="coupon-item" v-for="(item, index) in couponsList" :key="index">
|
||||
<view class="left">
|
||||
<view class="wave-line">
|
||||
<view class="wave" v-for="(item, index) in 12" :key="index"></view>
|
||||
</view>
|
||||
<view class="message">
|
||||
<view>
|
||||
<span v-if="item.couponType == 'DISCOUNT'">{{ item.discount }}折</span>
|
||||
<span v-else>{{ item.price }}元</span>
|
||||
</view>
|
||||
<view>满{{unitPrice(item.consumeThreshold) }}元可用</view>
|
||||
</view>
|
||||
<view class="circle circle-top"></view>
|
||||
<view class="circle circle-bottom"></view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="desc">
|
||||
<view v-if="item.scopeType">
|
||||
<span v-if="item.scopeType == 'ALL' && item.storeId == '0'">全平台</span>
|
||||
<span v-if="item.scopeType == 'PORTION_GOODS_CATEGORY'">仅限品类</span>
|
||||
<view v-else
|
||||
>{{
|
||||
item.storeName == "platform" ? "全平台" : item.storeName + "店铺"
|
||||
}}使用</view
|
||||
>
|
||||
</view>
|
||||
<view class="reason" v-if="item.reason">{{ item.reason }}</view>
|
||||
<view class="end-time">有效期至:{{ item.endTime }}</view>
|
||||
</view>
|
||||
<view
|
||||
class="receive"
|
||||
v-if="current == 0 && !routerVal.selectedCoupon.includes(item.id)"
|
||||
@click="clickWay(item)"
|
||||
>
|
||||
<text>立即</text><br />
|
||||
<text>使用</text>
|
||||
</view>
|
||||
<view class="used" v-if="current == 0 && routerVal.selectedCoupon.includes(item.id)" @click="clickWay(item)">
|
||||
<text>取消</text><br />
|
||||
<text>使用</text>
|
||||
</view>
|
||||
<view class="bg-quan">券</view>
|
||||
</view>
|
||||
<view class="b-content" :style="themeStyle">
|
||||
<view class="coupon-tabs">
|
||||
<u-tabs
|
||||
:list="list"
|
||||
:scrollable="false"
|
||||
:inactiveStyle="{ color: '#333' }"
|
||||
v-model:current="current"
|
||||
:lineColor="lightColor"
|
||||
:activeStyle="{ color: lightColor }"
|
||||
></u-tabs>
|
||||
</view>
|
||||
</div>
|
||||
|
||||
<scroll-view class="list-scroll-content" scroll-y>
|
||||
<u-empty
|
||||
mode="coupon"
|
||||
text="暂无优惠券"
|
||||
v-if="couponsList.length <= 0"
|
||||
></u-empty>
|
||||
|
||||
<view
|
||||
class="coupon-card"
|
||||
:class="{ 'coupon-used': current != 0 }"
|
||||
v-for="(item, index) in couponsList"
|
||||
:key="item.id || index"
|
||||
>
|
||||
<view class="coupon-card-left">
|
||||
<text class="coupon-price-symbol" v-if="item.couponType != 'DISCOUNT'">¥</text>
|
||||
<text class="coupon-price-value">
|
||||
{{ item.couponType == 'DISCOUNT' ? item.discount + '折' : unitPrice(item.price) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="coupon-divider"></view>
|
||||
<view class="coupon-card-right">
|
||||
<view class="coupon-info">
|
||||
<text class="coupon-card-name">
|
||||
<template v-if="item.scopeType == 'ALL' && item.storeId == '0'">全平台</template>
|
||||
<template v-else-if="item.scopeType == 'PORTION_GOODS_CATEGORY'">仅限品类</template>
|
||||
<template v-else>
|
||||
{{ item.storeName == 'platform' ? '全平台' : (item.storeName || '') + '店铺' }}
|
||||
</template>
|
||||
使用
|
||||
</text>
|
||||
<text class="coupon-card-desc">满{{ unitPrice(item.consumeThreshold) }}元可用</text>
|
||||
<text class="coupon-card-time" v-if="item.reason">{{ item.reason }}</text>
|
||||
<text class="coupon-card-time" v-if="item.endTime">有效期至:{{ item.endTime }}</text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="coupon-status-btn"
|
||||
v-if="current == 0 && !isSelected(item)"
|
||||
@click="clickWay(item)"
|
||||
>
|
||||
立即使用
|
||||
</view>
|
||||
<view
|
||||
class="coupon-status-btn cancel"
|
||||
v-else-if="current == 0 && isSelected(item)"
|
||||
@click="clickWay(item)"
|
||||
>
|
||||
取消使用
|
||||
</view>
|
||||
<view class="coupon-status-btn disabled" v-else>
|
||||
不可用
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useStore } from '@/store'
|
||||
import { useCoupon } from '@/api/trade.js'
|
||||
import { unitPrice } from '@/utils/filters.js'
|
||||
import { getThemeStyle } from '@/utils/theme'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const lightColor = computed(() => store.getters.lightColor)
|
||||
const themeStyle = computed(() => getThemeStyle(store.state.theme))
|
||||
const current = ref(0)
|
||||
const list = [
|
||||
{ name: '可用优惠券' },
|
||||
{ name: '不可用优惠券' },
|
||||
]
|
||||
const couponsList = ref<any[]>([])
|
||||
const routerVal = ref<Record<string, any>>({})
|
||||
const routerVal = ref<Record<string, any>>({
|
||||
selectedCoupon: [],
|
||||
way: '',
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
routerVal.value = options || {}
|
||||
const selectedCoupon = options?.selectedCoupon
|
||||
let selected: string[] = []
|
||||
if (Array.isArray(selectedCoupon)) {
|
||||
selected = selectedCoupon
|
||||
} else if (typeof selectedCoupon === 'string' && selectedCoupon) {
|
||||
selected = selectedCoupon.split(',')
|
||||
}
|
||||
routerVal.value = {
|
||||
...(options || {}),
|
||||
selectedCoupon: selected,
|
||||
}
|
||||
})
|
||||
|
||||
watch(current, (val) => {
|
||||
@@ -88,17 +113,17 @@ watch(current, (val) => {
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
couponsList.value = store.state.canUseCoupons || []
|
||||
})
|
||||
|
||||
function init() {
|
||||
couponsList.value = store.state.canUseCoupons
|
||||
function isSelected(coupon: any) {
|
||||
return (routerVal.value.selectedCoupon || []).includes(coupon.id)
|
||||
}
|
||||
|
||||
function clickWay(coupon: any) {
|
||||
useCoupon({
|
||||
memberCouponId: coupon.id,
|
||||
used: !routerVal.value.selectedCoupon.includes(coupon.id),
|
||||
used: !isSelected(coupon),
|
||||
way: routerVal.value.way,
|
||||
}).then((res) => {
|
||||
if (res.data.success) {
|
||||
@@ -113,160 +138,186 @@ function clickWay(coupon: any) {
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.desc {
|
||||
height: 220rpx;
|
||||
flex: 2;
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.b-content {
|
||||
background: #f7f8fa;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.end-time,
|
||||
.reason {
|
||||
color: #999;
|
||||
line-height: 1.5;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.empty {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
.coupon-tabs {
|
||||
background: #fff;
|
||||
height: 88rpx;
|
||||
box-shadow: 0 1rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.wrapper {
|
||||
background: #f9f9f9;
|
||||
|
||||
:deep(.u-tabs),
|
||||
:deep(.u-tabs__wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view-wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view),
|
||||
:deep(.u-tabs__wrapper__nav) {
|
||||
background: #fff;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item) {
|
||||
min-height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item__text) {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.list-scroll-content {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
width: 100%;
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coupon-card {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
position: relative;
|
||||
border: 1rpx solid #f0f1f5;
|
||||
overflow: hidden;
|
||||
|
||||
.coupon-tabs {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: #f7f8fa;
|
||||
border-radius: 50%;
|
||||
left: 204rpx;
|
||||
z-index: 2;
|
||||
box-shadow: inset 0 0 0 1rpx #eceef2;
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: -16rpx;
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: -16rpx;
|
||||
}
|
||||
|
||||
&.coupon-used {
|
||||
.coupon-card-left {
|
||||
background: linear-gradient(135deg, #f5f5f5 0%, #eeeeee 100%);
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.coupon-item {
|
||||
|
||||
.coupon-card-left {
|
||||
width: 220rpx;
|
||||
min-height: 180rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 220rpx;
|
||||
margin: 20rpx;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
color: #ff3b30;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #fff5f5 0%, #ffecec 100%);
|
||||
}
|
||||
|
||||
.left {
|
||||
height: 100%;
|
||||
width: 260rpx;
|
||||
background-color: $light-color;
|
||||
position: relative;
|
||||
.message {
|
||||
color: $font-color-white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin-top: 40rpx;
|
||||
.coupon-price-symbol {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
view:nth-child(1) {
|
||||
font-weight: bold;
|
||||
font-size: 60rpx;
|
||||
}
|
||||
.coupon-price-value {
|
||||
font-size: 56rpx;
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
letter-spacing: -1rpx;
|
||||
}
|
||||
|
||||
view:nth-child(2) {
|
||||
font-size: $font-sm;
|
||||
}
|
||||
}
|
||||
.coupon-divider {
|
||||
position: absolute;
|
||||
left: 220rpx;
|
||||
top: 24rpx;
|
||||
bottom: 24rpx;
|
||||
width: 0;
|
||||
border-left: 2rpx dashed #eceef2;
|
||||
}
|
||||
|
||||
.wave-line {
|
||||
height: 220rpx;
|
||||
width: 8rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: $light-color;
|
||||
overflow: hidden;
|
||||
.coupon-card-right {
|
||||
flex: 1;
|
||||
padding: 32rpx 32rpx 32rpx 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.wave {
|
||||
width: 8rpx;
|
||||
height: 16rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 0 16rpx 16rpx 0;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
.circle {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: $bg-color;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
z-index: 111;
|
||||
}
|
||||
.circle-top {
|
||||
top: -20rpx;
|
||||
right: -20rpx;
|
||||
}
|
||||
.circle-bottom {
|
||||
bottom: -20rpx;
|
||||
right: -20rpx;
|
||||
}
|
||||
.coupon-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.coupon-card-name {
|
||||
font-size: 30rpx;
|
||||
color: #111;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.coupon-card-desc {
|
||||
font-size: 24rpx;
|
||||
color: #8a8f99;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.coupon-card-time {
|
||||
font-size: 22rpx;
|
||||
color: #b0b3bf;
|
||||
}
|
||||
|
||||
.coupon-status-btn {
|
||||
flex-shrink: 0;
|
||||
padding: 16rpx 28rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--theme-light, #ff6b35), var(--theme-primary, #ff4b2b));
|
||||
|
||||
&:active {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 450rpx;
|
||||
font-size: $font-sm;
|
||||
height: 220rpx;
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
> view:nth-child(1) {
|
||||
color: #666666;
|
||||
margin-left: 20rpx;
|
||||
&.cancel {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
> view:nth-child(1) {
|
||||
color: #ff6262;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.receive {
|
||||
color: #ffffff;
|
||||
background-color: $main-color;
|
||||
border-radius: 50%;
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
text-align: center;
|
||||
margin-right: 30rpx;
|
||||
vertical-align: middle;
|
||||
padding-top: 8rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.used {
|
||||
color: #ffffff;
|
||||
background-color: black;
|
||||
border-radius: 50%;
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
text-align: center;
|
||||
margin-right: 30rpx;
|
||||
vertical-align: middle;
|
||||
padding-top: 8rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.bg-quan {
|
||||
width: 244rpx;
|
||||
height: 244rpx;
|
||||
border: 6rpx solid $main-color;
|
||||
border-radius: 50%;
|
||||
opacity: 0.1;
|
||||
color: $main-color;
|
||||
text-align: center;
|
||||
padding-top: 30rpx;
|
||||
font-size: 130rpx;
|
||||
position: absolute;
|
||||
right: -54rpx;
|
||||
bottom: -60rpx;
|
||||
}
|
||||
&.disabled {
|
||||
background: #ccc;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,29 +1,42 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<view class="page" :style="themeStyle">
|
||||
<u-navbar
|
||||
title="收藏"
|
||||
:fixed="true"
|
||||
:placeholder="true"
|
||||
:border="false"
|
||||
:auto-back="true"
|
||||
title=""
|
||||
></u-navbar>
|
||||
|
||||
<view class="tabs-wrap">
|
||||
<u-tabs
|
||||
:list="navList"
|
||||
:scrollable="false"
|
||||
:lineColor="lightColor"
|
||||
:activeStyle="{ color: lightColor, fontWeight: '600' }"
|
||||
:inactiveStyle="{ color: '#666' }"
|
||||
v-model:current="tabCurrentIndex"
|
||||
@change="onTabChange"
|
||||
></u-tabs>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
class="list-scroll"
|
||||
scroll-y
|
||||
enable-back-to-top
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="loadMore"
|
||||
>
|
||||
<template #center>
|
||||
<view class="slot-wrap">
|
||||
<u-tabs
|
||||
:lineColor="lightColor"
|
||||
:activeStyle="{ color: lightColor }"
|
||||
class="collect-tabs"
|
||||
:list="navList"
|
||||
:scrollable="false"
|
||||
v-model:current="tabCurrentIndex"
|
||||
></u-tabs>
|
||||
</view>
|
||||
</template>
|
||||
</u-navbar>
|
||||
<view class="collect-body">
|
||||
<!-- 显示商品栏 -->
|
||||
<!-- 商品 -->
|
||||
<view v-if="tabCurrentIndex === 0" class="tab-content">
|
||||
<u-empty style="margin-top: 40rpx" text="暂无收藏商品数据" mode="favor" v-if="goodsEmpty"></u-empty>
|
||||
<u-empty
|
||||
v-if="!goodsLoading && goodsEmpty"
|
||||
class="empty-box"
|
||||
text="暂无收藏商品"
|
||||
mode="favor"
|
||||
></u-empty>
|
||||
<template v-else>
|
||||
<u-swipe-action
|
||||
v-for="(item, index) in goodsList"
|
||||
@@ -34,26 +47,34 @@
|
||||
@open="openSwipeItem(item, 'goods')"
|
||||
:show="item.selected"
|
||||
:options="swipeOptions"
|
||||
@click="removeGoodsCollection(item, index)"
|
||||
@click="removeGoodsCollection(item)"
|
||||
:name="index"
|
||||
>
|
||||
<view class="goods" @click="goGoodsDetail(item)">
|
||||
<u-image width="131rpx" height="131rpx" :src="item.image" mode="aspectFit">
|
||||
<u-image width="140rpx" height="140rpx" radius="12rpx" :src="item.image" mode="aspectFill">
|
||||
<template #loading><u-loading-icon></u-loading-icon></template>
|
||||
</u-image>
|
||||
<view class="goods-intro">
|
||||
<view class="goods-name">{{ item.goodsName }}</view>
|
||||
<view class="goods-sn">{{ item.goods_sn }}</view>
|
||||
<view class="goods-name wes-2">{{ item.goodsName }}</view>
|
||||
<view class="goods-price">¥{{ unitPrice(item.price) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-swipe-action-item>
|
||||
</u-swipe-action>
|
||||
<view class="load-status" v-if="goodsList.length">
|
||||
{{ goodsFinished ? '没有更多了' : goodsLoading ? '加载中...' : '上拉加载更多' }}
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<!-- 显示收藏的店铺栏 -->
|
||||
|
||||
<!-- 店铺 -->
|
||||
<view v-else class="tab-content">
|
||||
<u-empty style="margin-top: 40rpx" text="暂无收藏店铺数据" mode="favor" v-if="storeEmpty"></u-empty>
|
||||
<u-empty
|
||||
v-if="!storeLoading && storeEmpty"
|
||||
class="empty-box"
|
||||
text="暂无收藏店铺"
|
||||
mode="favor"
|
||||
></u-empty>
|
||||
<template v-else>
|
||||
<u-swipe-action
|
||||
v-for="(item, index) in storeList"
|
||||
@@ -68,36 +89,51 @@
|
||||
:name="index"
|
||||
>
|
||||
<view class="store" @click="goStoreMainPage(item.id)">
|
||||
<view class="intro">
|
||||
<view class="store-logo">
|
||||
<u-image width="102rpx" height="102rpx" :src="item.storeLogo" :alt="item.storeName"
|
||||
mode="aspectFit">
|
||||
<template #loading><u-loading-icon></u-loading-icon></template>
|
||||
</u-image>
|
||||
</view>
|
||||
<view class="store-name">
|
||||
<view>{{ item.storeName }}</view>
|
||||
<u-tag size="mini" type="error" :color="mainColor" v-if="item.selfOperated"
|
||||
text="自营" mode="plain" shape="circle" />
|
||||
</view>
|
||||
<view class="store-collect">
|
||||
<view>进店逛逛</view>
|
||||
</view>
|
||||
<view class="store-logo">
|
||||
<u-image
|
||||
width="96rpx"
|
||||
height="96rpx"
|
||||
shape="circle"
|
||||
:src="item.storeLogo"
|
||||
mode="aspectFill"
|
||||
>
|
||||
<template #loading><u-loading-icon></u-loading-icon></template>
|
||||
</u-image>
|
||||
</view>
|
||||
<view class="store-info">
|
||||
<view class="store-name-row">
|
||||
<text class="store-name wes">{{ item.storeName }}</text>
|
||||
<u-tag
|
||||
v-if="item.selfOperated"
|
||||
size="mini"
|
||||
type="error"
|
||||
:color="mainColor"
|
||||
text="自营"
|
||||
plain
|
||||
shape="circle"
|
||||
/>
|
||||
</view>
|
||||
<view class="store-tip">左滑可取消收藏</view>
|
||||
</view>
|
||||
<view class="store-enter">进店逛逛</view>
|
||||
</view>
|
||||
</u-swipe-action-item>
|
||||
</u-swipe-action>
|
||||
<view class="load-status" v-if="storeList.length">
|
||||
{{ storeFinished ? '没有更多了' : storeLoading ? '加载中...' : '上拉加载更多' }}
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { onShow, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useStore } from '@/store'
|
||||
import { unitPrice } from '@/utils/filters.js'
|
||||
import { getThemeStyle } from '@/utils/theme'
|
||||
import {
|
||||
getGoodsCollection,
|
||||
getStoreCollection,
|
||||
@@ -109,6 +145,7 @@ const store = useStore()
|
||||
|
||||
const lightColor = computed(() => store.getters.lightColor)
|
||||
const mainColor = computed(() => store.getters.mainColor)
|
||||
const themeStyle = computed(() => getThemeStyle(store.state.theme))
|
||||
|
||||
const swipeOptions = computed(() => [
|
||||
{
|
||||
@@ -119,55 +156,93 @@ const swipeOptions = computed(() => [
|
||||
|
||||
const tabCurrentIndex = ref(0)
|
||||
const navList = ref([
|
||||
{ name: '商品(0)', params: { pageNumber: 1, pageSize: 10 } },
|
||||
{ name: '店铺(0)', params: { pageNumber: 1, pageSize: 10 } },
|
||||
{ name: '商品(0)' },
|
||||
{ name: '店铺(0)' },
|
||||
])
|
||||
|
||||
const goodsParams = ref({ pageNumber: 1, pageSize: 10 })
|
||||
const storeParams = ref({ pageNumber: 1, pageSize: 10 })
|
||||
|
||||
const goodsEmpty = ref(false)
|
||||
const storeEmpty = ref(false)
|
||||
const goodsList = ref<any[]>([])
|
||||
const storeList = ref<any[]>([])
|
||||
const goodsLoading = ref(false)
|
||||
const storeLoading = ref(false)
|
||||
const goodsFinished = ref(false)
|
||||
const storeFinished = ref(false)
|
||||
const refreshing = ref(false)
|
||||
const inited = ref(false)
|
||||
|
||||
onShow(() => {
|
||||
reloadOrLoadMore('reload')
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
reloadOrLoadMore('next')
|
||||
})
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
if (tabCurrentIndex.value === 0) {
|
||||
navList.value[0].params.pageNumber = 1
|
||||
goodsList.value = []
|
||||
fetchGoodsList()
|
||||
} else {
|
||||
navList.value[1].params.pageNumber = 1
|
||||
storeList.value = []
|
||||
fetchStoreList()
|
||||
if (!inited.value) {
|
||||
inited.value = true
|
||||
reloadAll()
|
||||
return
|
||||
}
|
||||
reloadCurrent()
|
||||
})
|
||||
|
||||
function hideLoadingIfNeeded() {
|
||||
if (store.state.isShowToast) uni.hideLoading()
|
||||
}
|
||||
|
||||
function reloadOrLoadMore(type: 'reload' | 'next') {
|
||||
if (type === 'next') {
|
||||
navList.value[tabCurrentIndex.value].params.pageNumber++
|
||||
if (tabCurrentIndex.value === 0) {
|
||||
fetchGoodsList()
|
||||
} else {
|
||||
fetchStoreList()
|
||||
}
|
||||
return
|
||||
function onTabChange(e: any) {
|
||||
const index = typeof e === 'number' ? e : e?.index
|
||||
if (typeof index === 'number') {
|
||||
tabCurrentIndex.value = index
|
||||
}
|
||||
navList.value[0].params.pageNumber = 1
|
||||
navList.value[1].params.pageNumber = 1
|
||||
if (tabCurrentIndex.value === 0 && !goodsList.value.length && !goodsEmpty.value) {
|
||||
reloadGoods()
|
||||
}
|
||||
if (tabCurrentIndex.value === 1 && !storeList.value.length && !storeEmpty.value) {
|
||||
reloadStore()
|
||||
}
|
||||
}
|
||||
|
||||
function onRefresh() {
|
||||
refreshing.value = true
|
||||
reloadCurrent()
|
||||
}
|
||||
|
||||
function loadMore() {
|
||||
if (tabCurrentIndex.value === 0) {
|
||||
if (goodsLoading.value || goodsFinished.value || goodsEmpty.value) return
|
||||
goodsParams.value.pageNumber++
|
||||
fetchGoodsList()
|
||||
} else {
|
||||
if (storeLoading.value || storeFinished.value || storeEmpty.value) return
|
||||
storeParams.value.pageNumber++
|
||||
fetchStoreList()
|
||||
}
|
||||
}
|
||||
|
||||
function reloadAll() {
|
||||
reloadGoods()
|
||||
reloadStore()
|
||||
}
|
||||
|
||||
function reloadCurrent() {
|
||||
if (tabCurrentIndex.value === 0) {
|
||||
reloadGoods()
|
||||
} else {
|
||||
reloadStore()
|
||||
}
|
||||
}
|
||||
|
||||
function reloadGoods() {
|
||||
goodsParams.value.pageNumber = 1
|
||||
goodsFinished.value = false
|
||||
goodsEmpty.value = false
|
||||
storeEmpty.value = false
|
||||
goodsList.value = []
|
||||
storeList.value = []
|
||||
fetchGoodsList()
|
||||
}
|
||||
|
||||
function reloadStore() {
|
||||
storeParams.value.pageNumber = 1
|
||||
storeFinished.value = false
|
||||
storeEmpty.value = false
|
||||
storeList.value = []
|
||||
fetchStoreList()
|
||||
}
|
||||
|
||||
@@ -182,9 +257,7 @@ function openSwipeItem(val: any, type: 'goods' | 'store') {
|
||||
function removeGoodsCollection(val: any) {
|
||||
deleteGoodsCollection(val.skuId).then((res) => {
|
||||
if (res.statusCode === 200) {
|
||||
goodsList.value = []
|
||||
navList.value[0].params.pageNumber = 1
|
||||
fetchGoodsList()
|
||||
reloadGoods()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -192,9 +265,7 @@ function removeGoodsCollection(val: any) {
|
||||
function removeStoreCollection(val: any) {
|
||||
deleteStoreCollection(val.id).then((res) => {
|
||||
if (res.statusCode === 200) {
|
||||
storeList.value = []
|
||||
navList.value[1].params.pageNumber = 1
|
||||
fetchStoreList()
|
||||
reloadStore()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -212,183 +283,210 @@ function goStoreMainPage(id: string) {
|
||||
}
|
||||
|
||||
function fetchGoodsList() {
|
||||
if (goodsLoading.value) return
|
||||
goodsLoading.value = true
|
||||
uni.showLoading({ title: '加载中' })
|
||||
getGoodsCollection(navList.value[0].params, 'GOODS')
|
||||
getGoodsCollection(goodsParams.value, 'GOODS')
|
||||
.then((res) => {
|
||||
goodsLoading.value = false
|
||||
refreshing.value = false
|
||||
hideLoadingIfNeeded()
|
||||
uni.stopPullDownRefresh()
|
||||
if (res.data.success) {
|
||||
const data = res.data.result
|
||||
navList.value[0].name = `商品(${data.total})`
|
||||
goodsEmpty.value = data.total === 0
|
||||
if (data.records?.length) {
|
||||
const records = data.records.map((item: any) => ({ ...item, selected: false }))
|
||||
navList.value[0].name = `商品(${data.total || 0})`
|
||||
goodsEmpty.value = !data.total
|
||||
const records = (data.records || []).map((item: any) => ({
|
||||
...item,
|
||||
selected: false,
|
||||
}))
|
||||
if (goodsParams.value.pageNumber === 1) {
|
||||
goodsList.value = records
|
||||
} else {
|
||||
goodsList.value.push(...records)
|
||||
}
|
||||
goodsFinished.value =
|
||||
!records.length || goodsList.value.length >= (data.total || 0)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
goodsLoading.value = false
|
||||
refreshing.value = false
|
||||
hideLoadingIfNeeded()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
}
|
||||
|
||||
function fetchStoreList() {
|
||||
if (storeLoading.value) return
|
||||
storeLoading.value = true
|
||||
uni.showLoading({ title: '加载中' })
|
||||
getStoreCollection(navList.value[1].params, 'STORE')
|
||||
getStoreCollection(storeParams.value, 'STORE')
|
||||
.then((res) => {
|
||||
storeLoading.value = false
|
||||
refreshing.value = false
|
||||
hideLoadingIfNeeded()
|
||||
uni.stopPullDownRefresh()
|
||||
if (res.data.success) {
|
||||
const data = res.data.result
|
||||
navList.value[1].name = `店铺(${data.total})`
|
||||
storeEmpty.value = data.total === 0
|
||||
if (data.records?.length) {
|
||||
const records = data.records.map((item: any) => ({ ...item, selected: false }))
|
||||
navList.value[1].name = `店铺(${data.total || 0})`
|
||||
storeEmpty.value = !data.total
|
||||
const records = (data.records || []).map((item: any) => ({
|
||||
...item,
|
||||
selected: false,
|
||||
}))
|
||||
if (storeParams.value.pageNumber === 1) {
|
||||
storeList.value = records
|
||||
} else {
|
||||
storeList.value.push(...records)
|
||||
}
|
||||
storeFinished.value =
|
||||
!records.length || storeList.value.length >= (data.total || 0)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
storeLoading.value = false
|
||||
refreshing.value = false
|
||||
hideLoadingIfNeeded()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page,
|
||||
.content {
|
||||
background: $page-color-base;
|
||||
height: 100%;
|
||||
}
|
||||
page {
|
||||
background: #f8f8f8;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f8f8f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tabs-wrap {
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.list-scroll {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.empty-box {
|
||||
margin-top: 120rpx;
|
||||
}
|
||||
|
||||
.collect-swipe,
|
||||
:deep(.u-swipe-action),
|
||||
:deep(.u-swipe-action-item),
|
||||
:deep(.u-swipe-action-item__content) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.u-swipe-action-item__content) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 24rpx;
|
||||
margin-top: 16rpx;
|
||||
background: #fff;
|
||||
|
||||
.goods-intro {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
justify-content: space-between;
|
||||
min-height: 140rpx;
|
||||
}
|
||||
|
||||
.slot-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.collect-tabs {
|
||||
width: 100%;
|
||||
.goods-price {
|
||||
margin-top: 16rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: var(--theme-light, #ff6b35);
|
||||
}
|
||||
}
|
||||
|
||||
.collect-body {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
.store {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
width: calc(100% - 32rpx);
|
||||
margin: 16rpx auto 0;
|
||||
padding: 24rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
width: 100%;
|
||||
}
|
||||
.store-logo {
|
||||
flex-shrink: 0;
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
:deep(.u-tabs),
|
||||
:deep(.u-tabs__wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view-wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view),
|
||||
:deep(.u-tabs__wrapper__nav) {
|
||||
width: 100%;
|
||||
}
|
||||
.store-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.collect-swipe,
|
||||
:deep(.u-swipe-action),
|
||||
:deep(.u-swipe-action-item),
|
||||
:deep(.u-swipe-action-item__content) {
|
||||
width: 100%;
|
||||
}
|
||||
.store-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
:deep(.u-swipe-action-item__content) {
|
||||
overflow: hidden;
|
||||
}
|
||||
.store-name {
|
||||
max-width: 360rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.goods {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid $border-color-light;
|
||||
min-height: 190rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx 20rpx;
|
||||
margin-top: 20rpx;
|
||||
width: 100%;
|
||||
.store-tip {
|
||||
margin-top: 10rpx;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.goods-intro {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: $font-base;
|
||||
line-height: 48rpx;
|
||||
margin-left: 30rpx;
|
||||
.store-enter {
|
||||
flex-shrink: 0;
|
||||
padding: 12rpx 20rpx;
|
||||
border-radius: 100px;
|
||||
border: 1rpx solid var(--theme-light, #ff6b35);
|
||||
color: var(--theme-light, #ff6b35);
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
line-height: 1.4em;
|
||||
font-size: 24rpx;
|
||||
max-height: 2.8em;
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.goods-sn {
|
||||
color: #cccccc;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
color: $light-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.store {
|
||||
background-color: #fff;
|
||||
border: 1px solid $border-color-light;
|
||||
border-radius: 16rpx;
|
||||
margin: 20rpx 10rpx;
|
||||
width: calc(100% - 20rpx);
|
||||
box-sizing: border-box;
|
||||
|
||||
.intro {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 30rpx 0 40rpx;
|
||||
min-height: 170rpx;
|
||||
|
||||
.store-logo {
|
||||
width: 102rpx;
|
||||
height: 102rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.store-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-left: 30rpx;
|
||||
line-height: 2em;
|
||||
|
||||
:first-child {
|
||||
font-size: $font-base;
|
||||
}
|
||||
}
|
||||
|
||||
.store-collect {
|
||||
flex-shrink: 0;
|
||||
border-left: 1px solid $border-color-light;
|
||||
padding-left: 20rpx;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: $font-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
.load-status {
|
||||
padding: 24rpx 0 8rpx;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
<mSearch
|
||||
ref="mSearchRef"
|
||||
class="mSearch-input-box"
|
||||
:show-clear="false"
|
||||
@clickLeft="back"
|
||||
:mode="2"
|
||||
:placeholder="defaultKeyword"
|
||||
@@ -271,7 +270,7 @@ import storage from '@/utils/storage'
|
||||
const store = useStore()
|
||||
const { proxy } = getCurrentInstance()!
|
||||
|
||||
const mSearchRef = ref<InstanceType<typeof mSearch> | null>(null)
|
||||
const mSearchRef = ref<any>(null)
|
||||
|
||||
const empty = ref(false)
|
||||
const scrollTop = ref(0)
|
||||
@@ -806,7 +805,7 @@ function doSearch(searchKeyword: string | false) {
|
||||
isShowSeachGoods.value = true
|
||||
if (mSearchRef.value) {
|
||||
mSearchRef.value.isShowSeachGoods = true
|
||||
mSearchRef.value.inputVal = resolvedKeyword
|
||||
mSearchRef.value.setInputValue(resolvedKeyword)
|
||||
}
|
||||
params.value.keyword = keyword.value
|
||||
params.value.pageNumber = 1
|
||||
|
||||
@@ -247,6 +247,26 @@ page {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background: #ffffff;
|
||||
height: 88rpx;
|
||||
box-shadow: 0 1rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
:deep(.u-tabs),
|
||||
:deep(.u-tabs__wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view-wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view),
|
||||
:deep(.u-tabs__wrapper__nav) {
|
||||
background: #fff;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item) {
|
||||
min-height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item__text) {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.box-content {
|
||||
margin: 20rpx 0;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<u-navbar :auto-back="false" @leftClick="back" left-icon-color="#fff" :bg-color="background.backgroundColor" :border="false">
|
||||
<div class="page" :style="themeStyle">
|
||||
<u-navbar
|
||||
:auto-back="false"
|
||||
@leftClick="back"
|
||||
left-icon-color="#fff"
|
||||
:bg-color="background.backgroundColor"
|
||||
:border="false"
|
||||
>
|
||||
</u-navbar>
|
||||
|
||||
<div class="wrapper-box">
|
||||
@@ -9,62 +15,64 @@
|
||||
<div class="bargain">
|
||||
<div class="flex bargain-item">
|
||||
<div class="goods-img">
|
||||
<u-image width="200" height="200" :src="bargainDetail.thumbnail"></u-image>
|
||||
<u-image width="200rpx" height="200rpx" :src="bargainDetail.thumbnail"></u-image>
|
||||
</div>
|
||||
<div class="goods-config">
|
||||
<div class="goods-title wes-2">
|
||||
{{bargainDetail.goodsName}}
|
||||
{{ bargainDetail.goodsName }}
|
||||
</div>
|
||||
<div class="flex price-box">
|
||||
<div class="purchase-price">
|
||||
当前:<span>¥{{ activityData.surplusPrice == 0 ? bargains.purchasePrice : unitPrice(activityData.surplusPrice)}}</span>
|
||||
</div>
|
||||
<div class="max-price">原价:<span>¥{{unitPrice(bargainDetail.price)}}</span>
|
||||
|
||||
当前:<text>¥{{ activityData.surplusPrice == 0 ? bargains.purchasePrice : unitPrice(activityData.surplusPrice) }}</text>
|
||||
</div>
|
||||
<div class="max-price">原价:<text>¥{{ unitPrice(bargainDetail.price) }}</text></div>
|
||||
</div>
|
||||
<div class="tips">{{bargainDetail.sellingPoint}}</div>
|
||||
<div class="tips">{{ bargainDetail.sellingPoint }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 砍价进度 -->
|
||||
<div class="bargain-progress">
|
||||
<u-line-progress class="line" :active-color="lightColor" striped striped-active :percent="totalPercent">
|
||||
<u-line-progress
|
||||
class="line"
|
||||
:active-color="lightColor"
|
||||
:percentage="totalPercent"
|
||||
:show-text="false"
|
||||
height="12"
|
||||
>
|
||||
</u-line-progress>
|
||||
<div class="flex tips">
|
||||
<div>已砍{{cutPrice}}元</div>
|
||||
<div>还剩{{activityData.surplusPrice}}元</div>
|
||||
<div>已砍{{ cutPrice }}元</div>
|
||||
<div>还剩{{ activityData.surplusPrice }}元</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 参与砍价 -->
|
||||
<div class="bargaining" v-if="!activityData.pass && activityData.status!='END'" @click="shareBargain">
|
||||
<div class="bargaining" v-if="!activityData.pass && activityData.status != 'END'" @click="shareBargain">
|
||||
邀请砍价
|
||||
</div>
|
||||
<!-- 立即购买 -->
|
||||
<div v-else>
|
||||
|
||||
<div v-if="activityData.status!='END'" class="buy" @click="getGoodsDetail">
|
||||
<div v-if="activityData.status != 'END'" class="buy" @click="getGoodsDetail">
|
||||
立即购买
|
||||
</div>
|
||||
</div>
|
||||
<!-- 我要开团 -->
|
||||
<div class="start" v-if="activityData.memberId != loginUser.id" @click="startOpenGroup">我要开团
|
||||
</div>
|
||||
<div class="start" v-if="activityData.memberId != loginUser.id" @click="startOpenGroup">我要开团</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 帮砍列表 -->
|
||||
<div class="box box2">
|
||||
<div class="bargain">
|
||||
<div class="bargain-title">帮忙砍</div>
|
||||
<div class="user-item flex" v-if="logData.length !=0 " v-for="(item,index) in logData" :key="index">
|
||||
<div class="user-item flex" v-if="logData.length != 0" v-for="(item, index) in logData" :key="index">
|
||||
<div>
|
||||
<u-image width="75" shape="circle" height="75" :src="item.kanjiaMemberFace"></u-image>
|
||||
<u-image width="75rpx" shape="circle" height="75rpx" :src="item.kanjiaMemberFace"></u-image>
|
||||
</div>
|
||||
<div class="user-config flex">
|
||||
<div class="user-name">
|
||||
<div>{{noPassByName(item.kanjiaMemberName)}}</div>
|
||||
<div>{{ noPassByName(item.kanjiaMemberName) }}</div>
|
||||
<div>使出吃的奶劲儿</div>
|
||||
</div>
|
||||
<div class="save">砍掉:<span>¥{{unitPrice(item.kanjiaPrice)}}</span></div>
|
||||
<div class="save">砍掉:<text>¥{{ unitPrice(item.kanjiaPrice) }}</text></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,36 +84,61 @@
|
||||
<view class="u-content">
|
||||
<u-parse :content="bargainDetail.mobileIntro" :tag-style="style"></u-parse>
|
||||
</view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 砍价 -->
|
||||
<u-modal title="恭喜您砍掉了" v-model:show="Bargaining" mask-close-able :show-confirm-button="false"
|
||||
:title-style="{color: lightColor}">
|
||||
<u-modal
|
||||
title="恭喜您砍掉了"
|
||||
v-model:show="Bargaining"
|
||||
:close-on-click-overlay="true"
|
||||
:show-confirm-button="false"
|
||||
>
|
||||
<view class="slot-content">
|
||||
<u-count-to :start-val="0" ref="uCountToRef" font-size="100" :color="lightColor" :end-val="kanjiaPrice"
|
||||
:decimals="2" :autoplay="autoplay"></u-count-to><span class="price">元</span>
|
||||
<u-count-to
|
||||
:start-val="0"
|
||||
ref="uCountToRef"
|
||||
font-size="100"
|
||||
:color="lightColor"
|
||||
:end-val="kanjiaPrice"
|
||||
:decimals="2"
|
||||
:autoplay="autoplay"
|
||||
></u-count-to>
|
||||
<text class="price">元</text>
|
||||
</view>
|
||||
</u-modal>
|
||||
<!-- 帮砍 -->
|
||||
|
||||
<u-modal :show-title="false" v-model:show="helpBargainFlage" :show-confirm-button="false">
|
||||
<u-modal title=" " v-model:show="helpBargainFlage" :show-confirm-button="false">
|
||||
<view class="help-bargain" @click="handleClickHelpBargain">
|
||||
<u-image width="100%" height="600rpx"
|
||||
src="https://lilishop-oss.oss-cn-beijing.aliyuncs.com/91631d5a66c7426bbe3f7d644ee41946.jpeg"></u-image>
|
||||
<u-image
|
||||
width="100%"
|
||||
height="600rpx"
|
||||
src="https://lilishop-oss.oss-cn-beijing.aliyuncs.com/91631d5a66c7426bbe3f7d644ee41946.jpeg"
|
||||
></u-image>
|
||||
<u-image class="help" width="300rpx" height="80rpx" src="/pages/promotion/static/help-bargain.png"></u-image>
|
||||
</view>
|
||||
</u-modal>
|
||||
|
||||
<!-- 分享 -->
|
||||
<shares @close="closeShare" :link="share()" type="kanjia" :thumbnail="bargainDetail.thumbnail"
|
||||
:goodsName="bargainDetail.goodsName" v-if="shareFlage " />
|
||||
<shares
|
||||
@close="closeShare"
|
||||
:link="share()"
|
||||
type="kanjia"
|
||||
:thumbnail="bargainDetail.thumbnail"
|
||||
:goodsName="bargainDetail.goodsName"
|
||||
v-if="shareFlage"
|
||||
/>
|
||||
|
||||
<!-- 购买 -->
|
||||
<popupGoods ref="popupGoodsRef" :buyMask="maskFlag" @closeBuy="closePopupBuy" :goodsDetail="bargainDetail"
|
||||
:goodsSpec="goodsSpec" v-if="bargainDetail.id " @handleClickSku="getGoodsDetail" />
|
||||
|
||||
<popupGoods
|
||||
ref="popupGoodsRef"
|
||||
:buyMask="maskFlag"
|
||||
@closeBuy="closePopupBuy"
|
||||
:goodsDetail="bargainDetail"
|
||||
:goodsSpec="goodsSpec"
|
||||
v-if="bargainDetail.id"
|
||||
@handleClickSku="getGoodsDetail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -128,10 +161,12 @@ import {
|
||||
import shares from '@/components/m-share/index'
|
||||
import config from '@/config/config'
|
||||
import { unitPrice, noPassByName, isLogin } from '@/utils/filters.js'
|
||||
import { getThemeStyle } from '@/utils/theme'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const lightColor = computed(() => store.getters.lightColor)
|
||||
const themeStyle = computed(() => getThemeStyle(store.state.theme))
|
||||
|
||||
const style = ref({
|
||||
img: 'display:block',
|
||||
@@ -205,8 +240,7 @@ watch(
|
||||
(val) => {
|
||||
if (val) {
|
||||
totalPercent.value =
|
||||
100 -
|
||||
Math.floor((val.surplusPrice / bargainDetail.value.price) * 100)
|
||||
100 - Math.floor((val.surplusPrice / bargainDetail.value.price) * 100)
|
||||
cutPrice.value = (
|
||||
bargainDetail.value.price - activityData.value.surplusPrice
|
||||
).toFixed(2)
|
||||
@@ -324,32 +358,44 @@ async function openActivity() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: $light-color !important;
|
||||
background-color: var(--theme-light, #ff6b35) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.slot-content {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
margin: 20rpx 0 80rpx 0;
|
||||
}
|
||||
|
||||
.price {
|
||||
margin-left: 10rpx;
|
||||
color: $light-color;
|
||||
color: var(--theme-light, #ff6b35);
|
||||
}
|
||||
|
||||
.price-box {
|
||||
align-items: center;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.wrapper-box {
|
||||
background: url("https://lili-system.oss-cn-beijing.aliyuncs.com/kanjia.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
height: 506rpx;
|
||||
background: url('https://lili-system.oss-cn-beijing.aliyuncs.com/kanjia.png') no-repeat top center;
|
||||
background-size: 100% 506rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-top: 420rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.box {
|
||||
@@ -357,99 +403,92 @@ page {
|
||||
border-radius: 20rpx;
|
||||
position: relative;
|
||||
width: 94%;
|
||||
margin: 0 auto;
|
||||
margin: 0 auto 20rpx;
|
||||
overflow: hidden;
|
||||
|
||||
> .bargain {
|
||||
padding: 32rpx;
|
||||
}
|
||||
}
|
||||
.box1 {
|
||||
top: 560rpx;
|
||||
}
|
||||
.box2 {
|
||||
top: 580rpx;
|
||||
}
|
||||
.box3 {
|
||||
top: 600rpx;
|
||||
}
|
||||
.box4 {
|
||||
top: 620 rpx;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.bargain-item {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.goods-config {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-left: 20rpx;
|
||||
|
||||
> .goods-title {
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
.max-price,
|
||||
.purchase-price {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.max-price {
|
||||
margin-left: 10rpx;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.purchase-price {
|
||||
color: $main-color;
|
||||
> span {
|
||||
color: var(--theme-primary, #ff3c2a);
|
||||
|
||||
> text {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.bargaining,
|
||||
.buy,
|
||||
.start {
|
||||
font-size: 24rpx;
|
||||
|
||||
width: 80%;
|
||||
margin: 50rpx auto 0 auto;
|
||||
margin: 50rpx auto 0;
|
||||
text-align: center;
|
||||
|
||||
font-size: 30rpx;
|
||||
padding: 18rpx;
|
||||
border-radius: 100px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.start {
|
||||
border: 1rpx solid $main-color;
|
||||
color: $main-color;
|
||||
border: 1rpx solid var(--theme-primary, #ff3c2a);
|
||||
color: var(--theme-primary, #ff3c2a);
|
||||
}
|
||||
|
||||
.bargaining,
|
||||
.buy {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
width: 80%;
|
||||
margin: 50rpx auto 0 auto;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
background-image: linear-gradient(
|
||||
25deg,
|
||||
$main-color,
|
||||
$light-color,
|
||||
$aider-light-color
|
||||
var(--theme-primary, #ff3c2a),
|
||||
var(--theme-light, #ff6b35),
|
||||
var(--theme-aider, #ff9f28)
|
||||
);
|
||||
|
||||
padding: 18rpx;
|
||||
border-radius: 100px;
|
||||
animation: mymove 5s infinite;
|
||||
-webkit-animation: mymove 5s infinite; /*Safari and Chrome*/
|
||||
animation-direction: alternate; /*轮流反向播放动画。*/
|
||||
animation-timing-function: ease-in-out; /*动画的速度曲线*/
|
||||
/* Safari 和 Chrome */
|
||||
-webkit-animation: mymove 5s infinite;
|
||||
-webkit-animation-direction: alternate; /*轮流反向播放动画。*/
|
||||
-webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes mymove {
|
||||
0% {
|
||||
transform: scale(1); /*开始为原始大小*/
|
||||
transform: scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.1); /*放大1.1倍*/
|
||||
transform: scale(1.1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1);
|
||||
@@ -458,65 +497,80 @@ page {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.bargain-progress {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.bargain-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: $light-color;
|
||||
color: var(--theme-light, #ff6b35);
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.user-item {
|
||||
margin: 40rpx 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-config {
|
||||
margin-left: 20rpx;
|
||||
flex: 8;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
> .user-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
font-size: 28rpx;
|
||||
max-width: 300rpx;
|
||||
overflow: hidden;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> div:nth-last-of-type(1) {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.save {
|
||||
color: $light-color;
|
||||
> span {
|
||||
flex-shrink: 0;
|
||||
color: var(--theme-light, #ff6b35);
|
||||
|
||||
> text {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.mobile-intro {
|
||||
|
||||
.u-content {
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@keyframes fontMove {
|
||||
0% {
|
||||
transform: scale(1); /*开始为原始大小*/
|
||||
transform: scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.1); /*放大1.1倍*/
|
||||
transform: scale(1.1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1);
|
||||
@@ -531,19 +585,13 @@ page {
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
> .help {
|
||||
margin-bottom: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
|
||||
margin-top: 40rpx;
|
||||
> .help {
|
||||
margin: 40rpx 0;
|
||||
border-radius: 20rpx;
|
||||
animation: fontMove 5s infinite;
|
||||
-webkit-animation: fontMove 5s infinite; /*Safari and Chrome*/
|
||||
animation-direction: alternate; /*轮流反向播放动画。*/
|
||||
animation-timing-function: ease-in-out; /*动画的速度曲线*/
|
||||
/* Safari 和 Chrome */
|
||||
-webkit-animation: fontMove 5s infinite;
|
||||
-webkit-animation-direction: alternate; /*轮流反向播放动画。*/
|
||||
-webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
<u-tabs
|
||||
:list="list"
|
||||
:scrollable="false"
|
||||
:inactiveStyle="{ color: '#333' }"
|
||||
v-model:current="current"
|
||||
:lineColor="lightColor"
|
||||
:activeStyle="{ color: lightColor }"
|
||||
@change="change"
|
||||
></u-tabs>
|
||||
<view v-if="showLoading" style="width:500rpx;margin:0 auto;text-align: center;height:800rpx;line-height: 800rpx;">
|
||||
@@ -183,9 +186,27 @@ function getMessage() {
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
<style lang="scss" scoped>
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.u-tabs),
|
||||
:deep(.u-tabs__wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view-wrapper),
|
||||
:deep(.u-tabs__wrapper__scroll-view),
|
||||
:deep(.u-tabs__wrapper__nav) {
|
||||
background: #fff;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item) {
|
||||
min-height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.u-tabs__wrapper__nav__item__text) {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
5
project.config.json
Normal file
5
project.config.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"setting": {
|
||||
"minifyWXML": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user