mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-13 20:38:54 +08:00
feat(buyer): 增强搜索功能并提升用户体验
- 新增 `getStoreById` 接口方法,用于获取包含评分在内的店铺信息 - `Search.vue` 新增搜索建议面板,展示搜索历史和热词,优化搜索体验 - 新增 `SearchSuggest.vue` 组件,用于展示搜索建议和搜索历史 - `App.vue` 根据路由元信息按条件设置页面标题 - 优化多个组件的布局与样式,让整体风格更统一 - 重构多个组件的跳转逻辑,改用路由跳转(`router.push`)替代新开窗口(`window.open`),提升用户体验
This commit is contained in:
@@ -2,55 +2,43 @@
|
||||
<div class="coupon-center">
|
||||
<BaseHeader></BaseHeader>
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="coupon-title">
|
||||
<router-link to="/">
|
||||
<img src="../assets/images/logo.png" width="120" alt="" />
|
||||
</router-link>
|
||||
<p>领券中心</p>
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
style="width: 400px"
|
||||
@keyup.enter="search"
|
||||
placeholder="搜索优惠券"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="coupon-page-title">领券中心</h2>
|
||||
|
||||
<div class="fontsize_18 recommend">推荐好券</div>
|
||||
|
||||
<empty v-if="!loading && list.length === 0" />
|
||||
<ul class="coupon-list" v-else-if="list.length > 0">
|
||||
<li v-for="(item, index) in list" class="coupon-item" :key="index">
|
||||
<div class="c-left">
|
||||
<div>
|
||||
<span
|
||||
v-if="item.couponType === 'PRICE'"
|
||||
class="fontsize_12 global_color"
|
||||
>¥<span class="price">{{ $filters.unitPrice(item.price) }}</span></span>
|
||||
<span
|
||||
v-if="item.couponType === 'DISCOUNT'"
|
||||
class="fontsize_12 global_color"
|
||||
><span class="price">{{ item.couponDiscount || item.discount }}</span>折</span>
|
||||
<span class="describe"
|
||||
>满{{ item.consumeThreshold }}元可用</span>
|
||||
</div>
|
||||
<p>使用范围:{{ useScope(item.scopeType, item.storeName) }}</p>
|
||||
<p>有效期:{{ item.endTime }}</p>
|
||||
<empty v-if="!loading && list.length === 0" />
|
||||
<ul class="coupon-list" v-else-if="list.length > 0">
|
||||
<li v-for="item in list" class="coupon-item" :key="item.id">
|
||||
<div class="c-left">
|
||||
<div class="coupon-amount">
|
||||
<span v-if="item.couponType === 'PRICE'" class="global_color">
|
||||
¥<span class="price">{{ $filters.unitPrice(item.price) }}</span>
|
||||
</span>
|
||||
<span v-if="item.couponType === 'DISCOUNT'" class="global_color">
|
||||
<span class="price">{{ item.couponDiscount || item.discount }}</span>折
|
||||
</span>
|
||||
<span class="describe">{{ thresholdText(item) }}</span>
|
||||
</div>
|
||||
<b></b>
|
||||
<a class="c-right" @click="receive(item)">立即领取</a>
|
||||
<i class="circle-top"></i>
|
||||
<i class="circle-bottom"></i>
|
||||
</li>
|
||||
</ul>
|
||||
<el-pagination v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="total"
|
||||
@current-change="changePageNum"
|
||||
class="pageration"
|
||||
@size-change="changePageSize"
|
||||
layout="total, sizes, prev, pager, next"></el-pagination>
|
||||
</div>
|
||||
<p class="coupon-name">
|
||||
<span class="scope-tag">{{ scopeTag(item.scopeType, item.storeName) }}</span>
|
||||
<span>{{ item.couponName }}</span>
|
||||
</p>
|
||||
<p class="coupon-time">有效期:{{ item.endTime }}</p>
|
||||
</div>
|
||||
<a
|
||||
class="c-right"
|
||||
:class="{ 'is-finished': isFinished(item) }"
|
||||
@click="receive(item)"
|
||||
>{{ isFinished(item) ? "已领完" : "立即领取" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="total"
|
||||
@current-change="changePageNum"
|
||||
class="pageration"
|
||||
@size-change="changePageSize"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
></el-pagination>
|
||||
</div>
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
@@ -65,7 +53,6 @@ export default {
|
||||
list: [], // 优惠券列表
|
||||
total: 0, // 优惠券总数
|
||||
loading: false,
|
||||
keyword: "",
|
||||
params: {
|
||||
// 请求参数
|
||||
getType: "FREE",
|
||||
@@ -75,13 +62,6 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 搜索优惠券
|
||||
search() {
|
||||
this.params.couponName = this.keyword.trim();
|
||||
this.params.pageNumber = 1;
|
||||
this.getList();
|
||||
},
|
||||
// 获取优惠券列表
|
||||
getList() {
|
||||
if (this.loading) return;
|
||||
this.loading = true;
|
||||
@@ -116,6 +96,7 @@ export default {
|
||||
},
|
||||
// 领取优惠券
|
||||
receive(item) {
|
||||
if (this.isFinished(item)) return;
|
||||
const userInfo = storage.getItem("userInfo");
|
||||
const isLogin = userInfo && JSON.parse(userInfo).username;
|
||||
if (!isLogin) {
|
||||
@@ -158,23 +139,22 @@ export default {
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 优惠券可用范围
|
||||
useScope(type, storeName) {
|
||||
let shop = "平台";
|
||||
let goods = "全部商品";
|
||||
if (storeName !== "platform") shop = storeName;
|
||||
switch (type) {
|
||||
case "ALL":
|
||||
goods = "全部商品";
|
||||
break;
|
||||
case "PORTION_GOODS":
|
||||
goods = "部分商品";
|
||||
break;
|
||||
case "PORTION_GOODS_CATEGORY":
|
||||
goods = "部分分类商品";
|
||||
break;
|
||||
}
|
||||
return `${shop}${goods}可用`;
|
||||
// 发行量已领完
|
||||
isFinished(item) {
|
||||
return Number(item.publishNum) > 0 && Number(item.receivedNum) >= Number(item.publishNum);
|
||||
},
|
||||
// 使用门槛文案
|
||||
thresholdText(item) {
|
||||
const threshold = Number(item.consumeThreshold);
|
||||
if (!threshold) return "无使用门槛";
|
||||
return `满${item.consumeThreshold}元可用`;
|
||||
},
|
||||
// 券范围。店铺名为 platform 时是平台通用券
|
||||
scopeTag(type, storeName) {
|
||||
if (type === "PORTION_GOODS") return "商品券";
|
||||
if (type === "PORTION_GOODS_CATEGORY") return "分类券";
|
||||
if (storeName && storeName !== "platform") return "店铺券";
|
||||
return "通用券";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
@@ -184,84 +164,156 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/styles/coupon.scss";
|
||||
|
||||
.coupon-center {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
|
||||
> div {
|
||||
margin: 10px auto;
|
||||
width: 1200px;
|
||||
}
|
||||
width: 1200px;
|
||||
margin: 0 auto 48px;
|
||||
background: transparent;
|
||||
}
|
||||
.coupon-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
margin-right: 500px;
|
||||
}
|
||||
border-bottom: 2px solid $theme_color;
|
||||
}
|
||||
.recommend {
|
||||
margin: 20px auto;
|
||||
font-weight: bold;
|
||||
width: 200px;
|
||||
.coupon-page-title {
|
||||
margin: 28px 0 20px;
|
||||
color: #171A26;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
.coupon-item {
|
||||
overflow: hidden;
|
||||
$claim-width: 55px;
|
||||
|
||||
.c-left {
|
||||
width: calc(100% - #{$claim-width});
|
||||
box-sizing: border-box;
|
||||
.coupon-list {
|
||||
gap: 16px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.coupon-item {
|
||||
width: calc((100% - 32px) / 3);
|
||||
height: auto;
|
||||
min-height: 132px;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
|
||||
b,
|
||||
i.circle-top,
|
||||
i.circle-bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
b {
|
||||
right: $claim-width;
|
||||
width: 0;
|
||||
background: none;
|
||||
border-right: 1px dashed #e0e0e0;
|
||||
.c-left {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
padding: 16px 16px 14px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.coupon-amount {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.describe {
|
||||
margin-left: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.coupon-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin: 0 0 8px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.scope-tag {
|
||||
flex-shrink: 0;
|
||||
padding: 0 6px;
|
||||
border-radius: 2px;
|
||||
background: #fff5f4;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.coupon-name span:last-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.coupon-time {
|
||||
margin: 0;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.c-right {
|
||||
width: $claim-width;
|
||||
position: relative;
|
||||
right: auto;
|
||||
top: auto;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
width: 48px;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: mixed;
|
||||
letter-spacing: 4px;
|
||||
font-size: 16px;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
&.is-finished {
|
||||
background: #c8c8c8;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i.circle-top,
|
||||
i.circle-bottom {
|
||||
right: calc(#{$claim-width} - 9px);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
i.circle-top {
|
||||
top: -9px;
|
||||
}
|
||||
|
||||
i.circle-bottom {
|
||||
bottom: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
.pageration {
|
||||
text-align: right;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 20px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user