mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-12 20:08:59 +08:00
feat(buyer): 增强搜索功能并提升用户体验
- 新增 `getStoreById` 接口方法,用于获取包含评分在内的店铺信息 - `Search.vue` 新增搜索建议面板,展示搜索历史和热词,优化搜索体验 - 新增 `SearchSuggest.vue` 组件,用于展示搜索建议和搜索历史 - `App.vue` 根据路由元信息按条件设置页面标题 - 优化多个组件的布局与样式,让整体风格更统一 - 重构多个组件的跳转逻辑,改用路由跳转(`router.push`)替代新开窗口(`window.open`),提升用户体验
This commit is contained in:
@@ -8,9 +8,8 @@
|
||||
<div class="item-detail-big-img" v-if="imgList[imgIndex]">
|
||||
<el-image
|
||||
:src="currentImg"
|
||||
:preview-src-list="previewList"
|
||||
fit="contain"
|
||||
style="width: 100%; height: 350px"
|
||||
fit="cover"
|
||||
style="width: 100%; height: 100%"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -44,27 +43,6 @@
|
||||
<div class="item-detail-title">
|
||||
<div class="item-detail-title-row">
|
||||
<span class="item-detail-name">{{ skuDetail.goodsName }}</span>
|
||||
<el-tag
|
||||
v-if="isECouponGoods"
|
||||
class="goods-type-tag"
|
||||
size="small"
|
||||
>
|
||||
电子卡券
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else-if="skuDetail.goodsType !== 'VIRTUAL_GOODS'"
|
||||
class="goods-type-tag"
|
||||
size="small"
|
||||
>
|
||||
实物商品
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else-if="skuDetail.goodsType == 'VIRTUAL_GOODS'"
|
||||
class="goods-type-tag"
|
||||
size="small"
|
||||
>
|
||||
虚拟商品
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sell-point">
|
||||
@@ -95,7 +73,7 @@
|
||||
<!-- 批发价格 -->
|
||||
<div v-if="!isECouponGoods && wholesaleNum && wholesaleNum.length">
|
||||
<div class="flex">
|
||||
<div class="item-price-title">价格</div>
|
||||
<div class="item-price-title"></div>
|
||||
|
||||
<div
|
||||
v-for="(item, index) in wholesalePrice"
|
||||
@@ -119,7 +97,6 @@
|
||||
|
||||
<!-- 普通价格 -->
|
||||
<div v-else>
|
||||
<span class="item-price-title">价格</span>
|
||||
<span class="item-price">{{ $filters.unitPrice(skuDetail.price, "¥") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -228,7 +205,7 @@
|
||||
</div>
|
||||
<!-- 选择颜色 -->
|
||||
<div
|
||||
class="item-select"
|
||||
class="item-select item-spec"
|
||||
v-for="(sku, index) in formatList"
|
||||
:key="sku.name"
|
||||
>
|
||||
@@ -257,7 +234,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="add-buy-car-box">
|
||||
<div class="item-select">
|
||||
<div class="item-select item-spec">
|
||||
<div class="item-select-title">
|
||||
<p>数量</p>
|
||||
</div>
|
||||
@@ -271,25 +248,10 @@
|
||||
:precision="0"
|
||||
@blur="changeCount"
|
||||
></el-input-number>
|
||||
<span class="inventory"> 库存{{ displayStock }}</span>
|
||||
<span class="inventory">(库存:{{ displayStock }})</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item-select"
|
||||
v-if="
|
||||
!isECouponGoods &&
|
||||
skuDetail.goodsType !== 'VIRTUAL_GOODS' &&
|
||||
skuDetail.weight !== 0
|
||||
"
|
||||
>
|
||||
<div class="item-select-title">
|
||||
<p>重量</p>
|
||||
</div>
|
||||
<div class="item-select-column">
|
||||
<span class="inventory">{{ skuDetail.weight }}kg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item-select add-buy-car-row"
|
||||
v-if="$route.query.way === 'POINT' && skuDetail.authFlag === 'PASS'"
|
||||
@@ -439,9 +401,6 @@ export default {
|
||||
const item = this.imgList[this.imgIndex];
|
||||
return item ? item.url || item : "";
|
||||
},
|
||||
previewList() {
|
||||
return this.imgList.map((item) => item.url || item);
|
||||
},
|
||||
wholesalePrice(key) {
|
||||
return this.wholesaleList.length
|
||||
? this.wholesaleList.map((item) => {
|
||||
@@ -624,6 +583,16 @@ export default {
|
||||
});
|
||||
},
|
||||
async collect() {
|
||||
if (!this.Cookies.getItem("accessToken") || !this.Cookies.getItem("userInfo")) {
|
||||
this.$router.push({
|
||||
path: "/login",
|
||||
query: {
|
||||
rePath: this.$route.path,
|
||||
query: JSON.stringify(this.$route.query || {}),
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 收藏商品
|
||||
if (this.isCollected) {
|
||||
let cancel = await cancelCollect("GOODS", this.skuDetail.id);
|
||||
@@ -717,16 +686,18 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
// 相册里会混进规格 JSON,只留图片地址;没有相册时用主图
|
||||
swiperGoodsImg() {
|
||||
this.skuDetail.specList.forEach((e) => {
|
||||
if (e.specName === "images") {
|
||||
this.imgList = this.skuDetail.goodsGalleryList.filter(i => i.indexOf("\"url\":") === -1 && i.indexOf("\"status\":") === -1);
|
||||
}
|
||||
const source = this.skuDetail.goodsGalleryList || [];
|
||||
const gallery = Array.from(source).filter((item) => {
|
||||
if (typeof item !== "string") return false;
|
||||
return item.indexOf('"url":') === -1 && item.indexOf('"status":') === -1;
|
||||
});
|
||||
if (!this.imgList) {
|
||||
this.imgList = [this.skuDetail.original];
|
||||
if (gallery.length) {
|
||||
this.imgList = gallery;
|
||||
return;
|
||||
}
|
||||
|
||||
this.imgList = this.skuDetail.original ? [this.skuDetail.original] : [];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
@@ -784,42 +755,50 @@ export default {
|
||||
}
|
||||
|
||||
.item-detail-left {
|
||||
width: 350px;
|
||||
width: 500px;
|
||||
margin-right: 32px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-detail-big-img {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
margin-bottom: 16px;
|
||||
background: #f5f5f5;
|
||||
|
||||
:deep(.el-image),
|
||||
:deep(.el-image__inner) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-image__inner) {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
#dplayer{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.item-detail-big-img img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item-detail-img-row {
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.item-detail-img-small {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
width: 86px;
|
||||
height: 86px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
background: #f5f5f5;
|
||||
|
||||
&.is-active {
|
||||
border-color: $theme_color;
|
||||
@@ -829,6 +808,7 @@ export default {
|
||||
.item-detail-img-small img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/*商品选购详情*/
|
||||
@@ -848,18 +828,11 @@ export default {
|
||||
|
||||
.item-detail-name {
|
||||
color: #171A26;
|
||||
font-weight: 600;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.goods-type-tag {
|
||||
flex-shrink: 0;
|
||||
--el-tag-bg-color: #fafafa;
|
||||
--el-tag-border-color: #eee;
|
||||
--el-tag-text-color: #666;
|
||||
}
|
||||
|
||||
.item-detail-express {
|
||||
font-size: 14px;
|
||||
padding: 2px 3px;
|
||||
@@ -1026,6 +999,22 @@ export default {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.item-spec {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
|
||||
.item-select-title {
|
||||
width: auto;
|
||||
margin-right: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.item-select-column {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-select-title {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
@@ -1215,8 +1204,9 @@ export default {
|
||||
|
||||
.inventory {
|
||||
padding-left: 8px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.view-video{
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="goods-detail-extra">
|
||||
<div class="goods-detail-extra__main">
|
||||
<div class="detail-layout">
|
||||
<div class="detail-main">
|
||||
<div class="detail-anchor" ref="tabNav" :class="{ 'is-stuck': anchorStuck }">
|
||||
<button
|
||||
v-for="tab in detailTabs"
|
||||
@@ -117,15 +120,25 @@
|
||||
<div class="detail-empty" v-else>暂无商品参数</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<StoreSide
|
||||
:store-id="skuDetail.storeId"
|
||||
:goods-id="skuDetail.goodsId"
|
||||
:sku-id="skuDetail.id"
|
||||
:store-name-fallback="skuDetail.storeName"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Refresh } from '@element-plus/icons-vue';
|
||||
import { goodsComment, goodsCommentNum } from '@/api/member.js';
|
||||
import StoreSide from './StoreSide.vue';
|
||||
|
||||
export default {
|
||||
components: { Refresh },
|
||||
components: { Refresh, StoreSide },
|
||||
name: 'ShowGoodsDetail',
|
||||
props: {
|
||||
detail: {
|
||||
@@ -277,8 +290,25 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.goods-detail-extra {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.goods-detail-extra__main {
|
||||
width: 1200px;
|
||||
margin: 16px auto 24px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-layout {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.detail-anchor {
|
||||
@@ -334,6 +364,7 @@ export default {
|
||||
.detail-panel {
|
||||
background: #fff;
|
||||
border-radius: 0 0 4px 4px;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.detail-section + .detail-section {
|
||||
@@ -381,7 +412,7 @@ export default {
|
||||
.item-param-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
margin: 16px 24px 24px;
|
||||
margin: 16px 24px 0;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
|
||||
419
buyer/src/components/goodsDetail/StoreSide.vue
Normal file
419
buyer/src/components/goodsDetail/StoreSide.vue
Normal file
@@ -0,0 +1,419 @@
|
||||
<template>
|
||||
<aside class="store-side" v-if="storeId">
|
||||
<div class="store-card">
|
||||
<div class="store-head" @click="goStore">
|
||||
<img
|
||||
v-if="store.storeLogo && !logoError"
|
||||
class="store-logo"
|
||||
:src="store.storeLogo"
|
||||
:alt="storeName"
|
||||
@error="logoError = true"
|
||||
/>
|
||||
<span v-else class="store-logo store-logo-fallback">{{ storeInitial }}</span>
|
||||
<div class="store-head-text">
|
||||
<p class="store-name">
|
||||
<span v-if="isSelfOperated" class="store-self">自营</span>
|
||||
<span class="store-name-text">{{ storeName }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="store-scores">
|
||||
<div class="score-item">
|
||||
<span class="score-label">描述</span>
|
||||
<span class="score-value">{{ formatScore(store.descriptionScore) }}</span>
|
||||
</div>
|
||||
<div class="score-item">
|
||||
<span class="score-label">服务</span>
|
||||
<span class="score-value">{{ formatScore(store.serviceScore) }}</span>
|
||||
</div>
|
||||
<div class="score-item">
|
||||
<span class="score-label">物流</span>
|
||||
<span class="score-value">{{ formatScore(store.deliveryScore) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="store-actions">
|
||||
<button type="button" class="store-btn" @click="contact">联系客服</button>
|
||||
<button type="button" class="store-btn" :class="{ 'is-on': collected }" @click="toggleCollect">
|
||||
{{ collected ? "已收藏" : "收藏店铺" }}
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="enter-store" @click="goStore">进店逛逛</button>
|
||||
</div>
|
||||
|
||||
<div class="recommend-card" v-if="recommends.length">
|
||||
<p class="recommend-title">店铺推荐</p>
|
||||
<div
|
||||
class="recommend-item"
|
||||
v-for="item in recommends"
|
||||
:key="item.id"
|
||||
@click="goGoods(item)"
|
||||
>
|
||||
<img class="recommend-img" :src="item.thumbnail || item.small" :alt="item.goodsName" />
|
||||
<div class="recommend-info">
|
||||
<p class="recommend-name">{{ item.goodsName }}</p>
|
||||
<div class="recommend-meta">
|
||||
<p class="recommend-price">{{ $filters.unitPrice(item.price, "¥") }}</p>
|
||||
<span class="recommend-sales">销量 {{ item.buyCount || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Message } from "@/utils/message";
|
||||
import { goodsList } from "@/api/goods";
|
||||
import { getStoreById } from "@/api/shopentry";
|
||||
import { cancelStoreCollect, collectStore, isStoreCollection } from "@/api/member";
|
||||
import imTalk from "@/components/mixes/talkIm";
|
||||
|
||||
export default {
|
||||
name: "StoreSide",
|
||||
mixins: [imTalk],
|
||||
props: {
|
||||
storeId: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
goodsId: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
skuId: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
storeNameFallback: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
store: {},
|
||||
logoError: false,
|
||||
collected: false,
|
||||
recommends: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
storeName() {
|
||||
return this.store.storeName || this.storeNameFallback || "店铺";
|
||||
},
|
||||
storeInitial() {
|
||||
return this.storeName.slice(0, 1);
|
||||
},
|
||||
// 自营标记后端可能是 true、1 或 "1"
|
||||
isSelfOperated() {
|
||||
const flag = this.store.selfOperated;
|
||||
return flag === true || flag === 1 || flag === "1";
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
storeId: {
|
||||
immediate: true,
|
||||
handler(id) {
|
||||
if (!id) return;
|
||||
this.logoError = false;
|
||||
this.loadStore(id);
|
||||
this.loadRecommend(id);
|
||||
this.loadCollected(id);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 没有评分或小于等于 0 时按满分展示
|
||||
formatScore(value) {
|
||||
const score = Number(value);
|
||||
if (!Number.isFinite(score) || score <= 0) return "5.00";
|
||||
return score.toFixed(2);
|
||||
},
|
||||
loadStore(id) {
|
||||
getStoreById(id).then((res) => {
|
||||
if (res.success && res.result) this.store = res.result;
|
||||
}).catch(() => {});
|
||||
},
|
||||
// 按销量取店内商品,去掉当前商品,最多 4 个
|
||||
loadRecommend(id) {
|
||||
goodsList({
|
||||
storeId: id,
|
||||
pageNumber: 1,
|
||||
pageSize: 8,
|
||||
sort: "buyCount",
|
||||
order: "desc",
|
||||
}).then((res) => {
|
||||
const records = (res.success && res.result && res.result.records) || [];
|
||||
this.recommends = records
|
||||
.filter((item) => String(item.goodsId) !== String(this.goodsId))
|
||||
.slice(0, 4);
|
||||
}).catch(() => {});
|
||||
},
|
||||
// 同时有 token 和用户信息才查收藏,避免残留 userInfo 触发登录跳转
|
||||
loadCollected(id) {
|
||||
if (!this.Cookies.getItem("accessToken") || !this.Cookies.getItem("userInfo")) return;
|
||||
isStoreCollection("STORE", id).then((res) => {
|
||||
if (res.success && res.result) this.collected = true;
|
||||
}).catch(() => {});
|
||||
},
|
||||
goStore() {
|
||||
this.$router.push({ path: "/merchant", query: { id: this.storeId } });
|
||||
},
|
||||
// 推荐商品新开详情页,店铺页仍在当前页打开
|
||||
goGoods(item) {
|
||||
const href = this.$router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId: item.id, goodsId: item.goodsId },
|
||||
}).href;
|
||||
window.open(href, "_blank");
|
||||
},
|
||||
contact() {
|
||||
this.IMService(this.storeId, this.goodsId, this.skuId);
|
||||
},
|
||||
// 未登录先去登录,并带回当前商品页
|
||||
async toggleCollect() {
|
||||
if (!this.Cookies.getItem("accessToken") || !this.Cookies.getItem("userInfo")) {
|
||||
this.$router.push({
|
||||
path: "/login",
|
||||
query: {
|
||||
rePath: this.$route.path,
|
||||
query: JSON.stringify(this.$route.query || {}),
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.collected) {
|
||||
const cancel = await cancelStoreCollect("STORE", this.storeId);
|
||||
if (cancel.success) {
|
||||
this.collected = false;
|
||||
Message.success("已取消收藏");
|
||||
}
|
||||
return;
|
||||
}
|
||||
const collect = await collectStore("STORE", this.storeId);
|
||||
if (collect.code === 200) {
|
||||
this.collected = true;
|
||||
Message.success("收藏店铺成功,可以前往个人中心我的收藏查看");
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.store-side {
|
||||
width: 260px;
|
||||
flex-shrink: 0;
|
||||
position: sticky;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
.store-card,
|
||||
.recommend-card {
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.store-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.store-head {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.store-logo {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #f0f0f0;
|
||||
flex-shrink: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.store-logo-fallback {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
background: $theme_color;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.store-head-text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.store-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
margin: 0;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.store-name-text {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.store-self {
|
||||
flex-shrink: 0;
|
||||
padding: 0 6px;
|
||||
border-radius: 2px;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.store-scores {
|
||||
display: flex;
|
||||
margin-top: 14px;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.score-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.score-label {
|
||||
display: block;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
color: $theme_color;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.store-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.store-btn,
|
||||
.enter-store {
|
||||
border: 1px solid #eee;
|
||||
background: #fff;
|
||||
color: #171A26;
|
||||
font-size: 13px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-btn {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.store-btn.is-on {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
background: #fff5f4;
|
||||
}
|
||||
|
||||
.enter-store {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.recommend-card {
|
||||
margin-top: 12px;
|
||||
padding: 12px 12px 4px;
|
||||
}
|
||||
|
||||
.recommend-title {
|
||||
margin: 0 0 8px;
|
||||
color: #171A26;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.recommend-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 8px 0 12px;
|
||||
cursor: pointer;
|
||||
|
||||
& + & {
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-img {
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.recommend-info {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.recommend-name {
|
||||
margin: 0;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.recommend-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.recommend-price {
|
||||
margin: 0;
|
||||
color: $theme_color;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.recommend-sales {
|
||||
flex-shrink: 0;
|
||||
color: #999;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user