|
@@ -1,256 +1,279 @@
|
|
|
<template>
|
|
<template>
|
|
|
<Theme>
|
|
<Theme>
|
|
|
<view class="wrap">
|
|
<view class="wrap">
|
|
|
- <Navbar fixed leftIconColor="var(--black)">
|
|
|
|
|
- <template #center>
|
|
|
|
|
- <view class="nav_title">
|
|
|
|
|
- {{ shopInfo.name || "店铺详情" }}
|
|
|
|
|
|
|
+ <Navbar
|
|
|
|
|
+ :bgColor="
|
|
|
|
|
+ scrollTop >= tabInitTop || activeNum == 1
|
|
|
|
|
+ ? 'var(--light)'
|
|
|
|
|
+ : 'transparent'
|
|
|
|
|
+ "
|
|
|
|
|
+ fixed
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #left>
|
|
|
|
|
+ <view class="nav_left">
|
|
|
|
|
+ <up-icon name="arrow-left" size="16" color="var(--light)"></up-icon>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
<template #right>
|
|
<template #right>
|
|
|
- <view class="nav_right" @click="toggleFavorite">
|
|
|
|
|
- <i
|
|
|
|
|
- class="icon-font"
|
|
|
|
|
- :class="isFavorite ? 'icon-heart-fill' : 'icon-heart'"
|
|
|
|
|
- ></i>
|
|
|
|
|
|
|
+ <view class="nav_right">
|
|
|
|
|
+ <view class="nav_item" @click.stop="collectClick">
|
|
|
|
|
+ <up-icon
|
|
|
|
|
+ name="star-fill"
|
|
|
|
|
+ size="16"
|
|
|
|
|
+ :color="isCollect ? 'var(--primary)' : 'var(--light)'"
|
|
|
|
|
+ ></up-icon>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="nav_item" @click.stop="shareClick">
|
|
|
|
|
+ <up-icon name="share" size="16" color="var(--light)"></up-icon>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
</Navbar>
|
|
</Navbar>
|
|
|
|
|
|
|
|
- <!-- 店铺头部信息 -->
|
|
|
|
|
- <view class="shop-header">
|
|
|
|
|
- <view class="shop-avatar">
|
|
|
|
|
- <image :src="shopInfo.avatar" class="avatar-img" />
|
|
|
|
|
- <view class="shop-status" :class="shopInfo.status">
|
|
|
|
|
- {{ shopInfo.status === "online" ? "营业中" : "休息中" }}
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="shop-info">
|
|
|
|
|
- <view class="shop-name">{{ shopInfo.name }}</view>
|
|
|
|
|
- <view class="shop-desc">{{ shopInfo.description }}</view>
|
|
|
|
|
- <view class="shop-stats">
|
|
|
|
|
- <view class="stat-item">
|
|
|
|
|
- <text class="stat-label">评分:</text>
|
|
|
|
|
- <text class="stat-value">{{ shopInfo.rating }}</text>
|
|
|
|
|
- <text class="stat-unit">分</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="stat-item">
|
|
|
|
|
- <text class="stat-label">销量:</text>
|
|
|
|
|
- <text class="stat-value">{{ shopInfo.sales }}</text>
|
|
|
|
|
- <text class="stat-unit">件</text>
|
|
|
|
|
|
|
+ <view class="content" id="conts" ref="contRef">
|
|
|
|
|
+ <scroll-view
|
|
|
|
|
+ scroll-with-animation
|
|
|
|
|
+ :scroll-into-view="scrollId"
|
|
|
|
|
+ :scroll-y="true"
|
|
|
|
|
+ class="scroll-view"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view id="scroll_item_0" class="scroll_item0">
|
|
|
|
|
+ <view id="tabInit" v-if="activeNum == 0">
|
|
|
|
|
+ <view class="swiper">
|
|
|
|
|
+ <Swiper
|
|
|
|
|
+ :listArr="swiperImgs"
|
|
|
|
|
+ autoplay
|
|
|
|
|
+ height="100%"
|
|
|
|
|
+ circular
|
|
|
|
|
+ indicator-dots
|
|
|
|
|
+ indicator-active-color="var(--black)"
|
|
|
|
|
+ indicator-color="var(--light)"
|
|
|
|
|
+ urlName="url"
|
|
|
|
|
+ borderRadius="0"
|
|
|
|
|
+ />
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="stat-item">
|
|
|
|
|
- <text class="stat-label">距离:</text>
|
|
|
|
|
- <text class="stat-value">{{ shopInfo.distance }}</text>
|
|
|
|
|
|
|
+ <view class="info_wrapper">
|
|
|
|
|
+ <view class="price_wrapper">
|
|
|
|
|
+ <view class="texts">
|
|
|
|
|
+ <rich-text
|
|
|
|
|
+ :nodes="MoneyAbouthtml(detail.price, true)"
|
|
|
|
|
+ ></rich-text>
|
|
|
|
|
+ <text class="original-price" v-if="detail.originalprice"
|
|
|
|
|
+ >{{ symbol.symbol }}{{ detail.originalprice }}</text
|
|
|
|
|
+ >
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="sale_right" v-if="detail.sale">
|
|
|
|
|
+ <trans _t="总销量" /> {{ detail.sale }}
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="info_name">{{
|
|
|
|
|
+ detail.title || detail.goodsName
|
|
|
|
|
+ }}</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 店铺标签 -->
|
|
|
|
|
- <view class="shop-tags">
|
|
|
|
|
- <text class="tag" v-for="tag in shopInfo.tags" :key="tag">
|
|
|
|
|
- {{ tag }}
|
|
|
|
|
- </text>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 店铺功能按钮 -->
|
|
|
|
|
- <view class="shop-actions">
|
|
|
|
|
- <view class="action-btn" @click="contactShop">
|
|
|
|
|
- <i class="icon-font icon-chat"></i>
|
|
|
|
|
- <text>联系店铺</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="action-btn" @click="viewLocation">
|
|
|
|
|
- <i class="icon-font icon-location"></i>
|
|
|
|
|
- <text>查看位置</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="action-btn" @click="shareShop">
|
|
|
|
|
- <i class="icon-font icon-share"></i>
|
|
|
|
|
- <text>分享店铺</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 商品分类 -->
|
|
|
|
|
- <view class="category-section">
|
|
|
|
|
- <view class="section-title">商品分类</view>
|
|
|
|
|
- <view class="category-list">
|
|
|
|
|
- <view
|
|
|
|
|
- class="category-item"
|
|
|
|
|
- v-for="category in categories"
|
|
|
|
|
- :key="category.id"
|
|
|
|
|
- @click="selectCategory(category)"
|
|
|
|
|
- :class="{ active: selectedCategory === category.id }"
|
|
|
|
|
- >
|
|
|
|
|
- <image :src="category.icon" class="category-icon" />
|
|
|
|
|
- <text class="category-name">{{ category.name }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 商品列表 -->
|
|
|
|
|
- <view class="products-section">
|
|
|
|
|
- <view class="section-title">热销商品</view>
|
|
|
|
|
- <view class="products-grid">
|
|
|
|
|
- <view
|
|
|
|
|
- class="product-item"
|
|
|
|
|
- v-for="product in products"
|
|
|
|
|
- :key="product.id"
|
|
|
|
|
- @click="toProductDetail(product)"
|
|
|
|
|
- >
|
|
|
|
|
- <image :src="product.image" class="product-image" />
|
|
|
|
|
- <view class="product-info">
|
|
|
|
|
- <text class="product-name">{{ product.name }}</text>
|
|
|
|
|
- <view class="product-price">
|
|
|
|
|
- <text class="current-price"
|
|
|
|
|
- >{{ symbol.symbol }}{{ product.price }}</text
|
|
|
|
|
- >
|
|
|
|
|
- <text class="original-price" v-if="product.originalPrice"
|
|
|
|
|
- >{{ symbol.symbol }}{{ product.originalPrice }}</text
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <view id="scroll_item_1" class="scroll_item1" v-if="activeNum == 0">
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="detail_wrapper"
|
|
|
|
|
+ v-if="detail.propArr && detail.propArr.length"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="module_title">
|
|
|
|
|
+ <trans _t="规格参数" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <Norm :item="detail.propArr" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="detail_wrapper" v-if="detail.desc">
|
|
|
|
|
+ <view class="module_title">
|
|
|
|
|
+ <trans _t="产品详情" />
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="product-sales">已售{{ product.sales }}件</view>
|
|
|
|
|
|
|
+ <view class="desc_imgs">
|
|
|
|
|
+ <rich-text class="desc_cont" :nodes="detail.desc"></rich-text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+ <view class="footer_btns">
|
|
|
|
|
+ <view class="btn_wrapper">
|
|
|
|
|
+ <view class="btn btn_add" @click="add('add')">
|
|
|
|
|
+ <trans _t="加入购物车" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="btn btn_buy" @click="add('buy')">
|
|
|
|
|
+ <trans _t="立即购买" />
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <quantityPopup :detail="detail" ref="quantityRef" />
|
|
|
</Theme>
|
|
</Theme>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, computed, onMounted } from "vue";
|
|
|
|
|
|
|
+import { ref, onMounted, nextTick, computed } from "vue";
|
|
|
import Navbar from "@/components/navbar";
|
|
import Navbar from "@/components/navbar";
|
|
|
-import { useSystemStore } from "@/store";
|
|
|
|
|
|
|
+import { SELLER_GOODS_INFO } from "@/api";
|
|
|
|
|
+import { onLoad, onPageScroll } from "@dcloudio/uni-app";
|
|
|
import { t } from "@/locale";
|
|
import { t } from "@/locale";
|
|
|
-import { onLoad } from "@dcloudio/uni-app";
|
|
|
|
|
-
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ useShopStore,
|
|
|
|
|
+ useSystemStore,
|
|
|
|
|
+ useTabbarStore,
|
|
|
|
|
+ useCacheStore,
|
|
|
|
|
+} from "@/store";
|
|
|
|
|
+import Swiper from "@/components/swiper";
|
|
|
|
|
+import {
|
|
|
|
|
+ systemInfo,
|
|
|
|
|
+ openUrl,
|
|
|
|
|
+ refresh,
|
|
|
|
|
+ query,
|
|
|
|
|
+ MoneyAbouthtml,
|
|
|
|
|
+ Toast,
|
|
|
|
|
+ TimeOut,
|
|
|
|
|
+ urlStrToArr,
|
|
|
|
|
+} from "@/utils";
|
|
|
|
|
+import Tab from "@/components/tabs";
|
|
|
|
|
+import ImageGrid from "@/components/ImageGrid.vue";
|
|
|
|
|
+import selectSpec from "@/pages/shop/components/select_spec";
|
|
|
|
|
+import Norm from "@/pages/shop/components/norm";
|
|
|
|
|
+import quantityPopup from "./components/quantity_popup";
|
|
|
|
|
+
|
|
|
|
|
+const useShop = useShopStore();
|
|
|
const useSystem = useSystemStore();
|
|
const useSystem = useSystemStore();
|
|
|
-const symbol = computed(() => useSystem.getSymbol);
|
|
|
|
|
-
|
|
|
|
|
-// 店铺信息
|
|
|
|
|
-const shopInfo = ref({
|
|
|
|
|
- id: 1,
|
|
|
|
|
- name: "时尚潮流店",
|
|
|
|
|
- description: "专注时尚潮流服饰,品质保证,为您提供最优质的商品和服务",
|
|
|
|
|
- avatar: "/static/shop/shop1.png",
|
|
|
|
|
- rating: 4.8,
|
|
|
|
|
- sales: 1234,
|
|
|
|
|
- distance: "1.2km",
|
|
|
|
|
- status: "online",
|
|
|
|
|
- tags: ["时尚", "潮流", "品质", "正品"],
|
|
|
|
|
|
|
+const useTabbar = useTabbarStore();
|
|
|
|
|
+const useCache = useCacheStore();
|
|
|
|
|
+
|
|
|
|
|
+const goodsId = ref(0);
|
|
|
|
|
+const detail = ref({});
|
|
|
|
|
+const activeNum = ref(0);
|
|
|
|
|
+const isCollect = ref(false);
|
|
|
|
|
+const selectRef = ref(null);
|
|
|
|
|
+const quantityRef = ref(null);
|
|
|
|
|
+
|
|
|
|
|
+const tabInitTop = ref(0);
|
|
|
|
|
+const initTab = ref(0);
|
|
|
|
|
+const scrollTop = ref(0);
|
|
|
|
|
+const tabList = ["详情", "评论"];
|
|
|
|
|
+const contRef = ref(null);
|
|
|
|
|
+const scrollId = ref("scroll_item_0");
|
|
|
|
|
+
|
|
|
|
|
+const swiperImgs = computed(() => {
|
|
|
|
|
+ if (detail.value.item_imgs && detail.value.item_imgs.length) {
|
|
|
|
|
+ return detail.value.item_imgs.slice(0, 6);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (detail.value.picurl) {
|
|
|
|
|
+ return [{ url: detail.value.picurl }];
|
|
|
|
|
+ }
|
|
|
|
|
+ return [];
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-// 是否收藏
|
|
|
|
|
-const isFavorite = ref(false);
|
|
|
|
|
-
|
|
|
|
|
-// 选中的分类
|
|
|
|
|
-const selectedCategory = ref(1);
|
|
|
|
|
-
|
|
|
|
|
-// 商品分类
|
|
|
|
|
-const categories = ref([
|
|
|
|
|
- { id: 1, name: "全部", icon: "/static/shop/category_all.png" },
|
|
|
|
|
- { id: 2, name: "上衣", icon: "/static/shop/category_top.png" },
|
|
|
|
|
- { id: 3, name: "裤子", icon: "/static/shop/category_pants.png" },
|
|
|
|
|
- { id: 4, name: "鞋子", icon: "/static/shop/category_shoes.png" },
|
|
|
|
|
- { id: 5, name: "配饰", icon: "/static/shop/category_accessories.png" },
|
|
|
|
|
-]);
|
|
|
|
|
-
|
|
|
|
|
-// 商品列表
|
|
|
|
|
-const products = ref([
|
|
|
|
|
- {
|
|
|
|
|
- id: 1,
|
|
|
|
|
- name: "时尚T恤",
|
|
|
|
|
- image: "/static/shop/product1.png",
|
|
|
|
|
- price: "99.00",
|
|
|
|
|
- originalPrice: "129.00",
|
|
|
|
|
- sales: 234,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 2,
|
|
|
|
|
- name: "休闲牛仔裤",
|
|
|
|
|
- image: "/static/shop/product2.png",
|
|
|
|
|
- price: "199.00",
|
|
|
|
|
- originalPrice: "259.00",
|
|
|
|
|
- sales: 156,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 3,
|
|
|
|
|
- name: "运动鞋",
|
|
|
|
|
- image: "/static/shop/product3.png",
|
|
|
|
|
- price: "299.00",
|
|
|
|
|
- originalPrice: "399.00",
|
|
|
|
|
- sales: 89,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 4,
|
|
|
|
|
- name: "时尚帽子",
|
|
|
|
|
- image: "/static/shop/product4.png",
|
|
|
|
|
- price: "59.00",
|
|
|
|
|
- originalPrice: "79.00",
|
|
|
|
|
- sales: 67,
|
|
|
|
|
- },
|
|
|
|
|
-]);
|
|
|
|
|
-
|
|
|
|
|
-// 切换收藏状态
|
|
|
|
|
-const toggleFavorite = () => {
|
|
|
|
|
- isFavorite.value = !isFavorite.value;
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: isFavorite.value ? "已收藏" : "已取消收藏",
|
|
|
|
|
- icon: "none",
|
|
|
|
|
|
|
+const currency = computed(() => useSystem.getCurrency);
|
|
|
|
|
+const symbol = computed(() => useSystem.getSymbol);
|
|
|
|
|
+
|
|
|
|
|
+const top = systemInfo().statusBarHeight || 0;
|
|
|
|
|
+
|
|
|
|
|
+const tabClick = (item, index) => {
|
|
|
|
|
+ activeNum.value = index;
|
|
|
|
|
+ getHeight("scroll_item_" + index);
|
|
|
|
|
+ let newTop =
|
|
|
|
|
+ index == 0
|
|
|
|
|
+ ? 0
|
|
|
|
|
+ : index == 1
|
|
|
|
|
+ ? height0.value - 44 - top - initTab.value
|
|
|
|
|
+ : height0.value + height1.value - 44 - top - initTab.value;
|
|
|
|
|
+ uni.pageScrollTo({
|
|
|
|
|
+ scrollTop: newTop,
|
|
|
|
|
+ duration: 300,
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 联系店铺
|
|
|
|
|
-const contactShop = () => {
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: "联系店铺功能开发中",
|
|
|
|
|
- icon: "none",
|
|
|
|
|
- });
|
|
|
|
|
|
|
+const height0 = ref(0);
|
|
|
|
|
+const height1 = ref(0);
|
|
|
|
|
+
|
|
|
|
|
+const getHeight = async (id) => {
|
|
|
|
|
+ let ids = "#" + id;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await query(ids);
|
|
|
|
|
+ if (id == "scroll_item_0" && !height0.value) {
|
|
|
|
|
+ height0.value = res.height;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (id == "scroll_item_1" && !height1.value) {
|
|
|
|
|
+ height1.value = res.height;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 查看位置
|
|
|
|
|
-const viewLocation = () => {
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: "查看位置功能开发中",
|
|
|
|
|
- icon: "none",
|
|
|
|
|
- });
|
|
|
|
|
|
|
+const collectClick = () => {
|
|
|
|
|
+ // TODO: 实现收藏功能
|
|
|
|
|
+ Toast("收藏功能待实现");
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 分享店铺
|
|
|
|
|
-const shareShop = () => {
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: "分享店铺功能开发中",
|
|
|
|
|
- icon: "none",
|
|
|
|
|
- });
|
|
|
|
|
|
|
+const shareClick = () => {
|
|
|
|
|
+ // TODO: 实现分享功能
|
|
|
|
|
+ Toast("分享功能待实现");
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 选择分类
|
|
|
|
|
-const selectCategory = (category) => {
|
|
|
|
|
- selectedCategory.value = category.id;
|
|
|
|
|
- // 这里可以根据分类筛选商品
|
|
|
|
|
- console.log("选择分类:", category.name);
|
|
|
|
|
|
|
+const add = (type) => {
|
|
|
|
|
+ quantityRef.value && quantityRef.value.open(type);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 跳转到商品详情
|
|
|
|
|
-const toProductDetail = (product) => {
|
|
|
|
|
- uni.navigateTo({
|
|
|
|
|
- url: `/pagesBuyer/shop/product?id=${product.id}`,
|
|
|
|
|
|
|
+const getDetail = async () => {
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ id: goodsId.value,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await SELLER_GOODS_INFO(params);
|
|
|
|
|
+ detail.value = res.data;
|
|
|
|
|
+ isCollect.value = res.data.isCollect ? true : false;
|
|
|
|
|
+
|
|
|
|
|
+ if (res.data.skudesc) {
|
|
|
|
|
+ detail.value.propArr = parseSkuDesc(res.data.skudesc);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Toast(error.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 解析skudesc字段,转换为规格参数数组
|
|
|
|
|
+const parseSkuDesc = (skudesc) => {
|
|
|
|
|
+ if (!skudesc) return [];
|
|
|
|
|
+
|
|
|
|
|
+ const specs = skudesc.split(";");
|
|
|
|
|
+ const propArr = [];
|
|
|
|
|
+
|
|
|
|
|
+ specs.forEach((spec) => {
|
|
|
|
|
+ if (spec.trim()) {
|
|
|
|
|
+ const [name, value] = spec.split(":");
|
|
|
|
|
+ if (name && value) {
|
|
|
|
|
+ propArr.push({
|
|
|
|
|
+ name: name.trim(),
|
|
|
|
|
+ value: value.trim(),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ return propArr;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+onPageScroll((e) => {
|
|
|
|
|
+ scrollTop.value = e.scrollTop;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
onLoad((options) => {
|
|
onLoad((options) => {
|
|
|
- // 从页面参数获取店铺信息
|
|
|
|
|
- if (options.id) {
|
|
|
|
|
- shopInfo.value.id = options.id;
|
|
|
|
|
- }
|
|
|
|
|
- if (options.name) {
|
|
|
|
|
- shopInfo.value.name = decodeURIComponent(options.name);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const { id = 0 } = options;
|
|
|
|
|
+ goodsId.value = id;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
- // 页面加载完成后的逻辑
|
|
|
|
|
|
|
+ nextTick(async () => {
|
|
|
|
|
+ getDetail();
|
|
|
|
|
+ const scrollItem0 = await query("#tabInit");
|
|
|
|
|
+ tabInitTop.value = scrollItem0.height;
|
|
|
|
|
+ const scrollTab = await query("#tab");
|
|
|
|
|
+ initTab.value = scrollTab.height;
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -258,249 +281,276 @@ onMounted(() => {
|
|
|
@import url("@/style.less");
|
|
@import url("@/style.less");
|
|
|
|
|
|
|
|
.wrap {
|
|
.wrap {
|
|
|
|
|
+ background-color: var(--bg);
|
|
|
min-height: 100vh;
|
|
min-height: 100vh;
|
|
|
- background: var(--bg);
|
|
|
|
|
- padding-bottom: 30rpx;
|
|
|
|
|
|
|
|
|
|
- .nav_title {
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
- font-size: 36rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
|
|
+ .nav_left {
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
|
|
+ border-radius: 10rpx;
|
|
|
|
|
+ width: 50rpx;
|
|
|
|
|
+ height: 50rpx;
|
|
|
|
|
+ .flex_center();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.nav_right {
|
|
.nav_right {
|
|
|
- color: var(--primary);
|
|
|
|
|
- font-size: 40rpx;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .shop-header {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- background: var(--light);
|
|
|
|
|
- padding: 30rpx;
|
|
|
|
|
- margin-bottom: 20rpx;
|
|
|
|
|
-
|
|
|
|
|
- .shop-avatar {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- margin-right: 24rpx;
|
|
|
|
|
-
|
|
|
|
|
- .avatar-img {
|
|
|
|
|
- width: 120rpx;
|
|
|
|
|
- height: 120rpx;
|
|
|
|
|
- border-radius: 20rpx;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .flex_center();
|
|
|
|
|
+ gap: 12rpx;
|
|
|
|
|
|
|
|
- .shop-status {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- bottom: -8rpx;
|
|
|
|
|
- left: 50%;
|
|
|
|
|
- transform: translateX(-50%);
|
|
|
|
|
- font-size: 20rpx;
|
|
|
|
|
- padding: 4rpx 12rpx;
|
|
|
|
|
- border-radius: 20rpx;
|
|
|
|
|
- color: var(--light);
|
|
|
|
|
-
|
|
|
|
|
- &.online {
|
|
|
|
|
- background: var(--success);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .nav_item {
|
|
|
|
|
+ width: 50rpx;
|
|
|
|
|
+ height: 50rpx;
|
|
|
|
|
+ .flex_center();
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
|
|
+ color: var(--light);
|
|
|
|
|
+ border-radius: 10rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- &.offline {
|
|
|
|
|
- background: var(--text-01);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .tab {
|
|
|
|
|
+ z-index: 11;
|
|
|
|
|
+ background-color: var(--light);
|
|
|
|
|
+ &.active_tab {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 44px;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .shop-info {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
|
|
+ .content {
|
|
|
|
|
+ padding-bottom: 148rpx;
|
|
|
|
|
+ margin-top: -44px;
|
|
|
|
|
|
|
|
- .shop-name {
|
|
|
|
|
- font-size: 36rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
|
|
+ .scroll_item0 {
|
|
|
|
|
+ /deep/ .swiper_list {
|
|
|
|
|
+ object-fit: cover;
|
|
|
|
|
+ aspect-ratio: 1 / 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .shop-desc {
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- color: var(--text-01);
|
|
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
- line-height: 1.4;
|
|
|
|
|
|
|
+ .swiper {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+
|
|
|
|
|
+ /deep/ .uni-swiper-dots-horizontal {
|
|
|
|
|
+ bottom: 40px;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .shop-stats {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 24rpx;
|
|
|
|
|
|
|
+ .info_wrapper {
|
|
|
|
|
+ background-color: var(--light);
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ border-radius: 60rpx 60rpx 0 0;
|
|
|
|
|
+ margin-top: -30px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
|
|
|
- .stat-item {
|
|
|
|
|
- display: flex;
|
|
|
|
|
|
|
+ .price_wrapper {
|
|
|
|
|
+ .hor(space-between);
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
-
|
|
|
|
|
- .stat-label {
|
|
|
|
|
- font-size: 22rpx;
|
|
|
|
|
- color: var(--text-01);
|
|
|
|
|
- margin-right: 4rpx;
|
|
|
|
|
|
|
+ height: 60rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: var(--red);
|
|
|
|
|
+ .size(40rpx);
|
|
|
|
|
+ margin-bottom: 24rpx;
|
|
|
|
|
+
|
|
|
|
|
+ .texts {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: baseline;
|
|
|
|
|
+ line-height: 1;
|
|
|
|
|
+ margin-left: 8rpx;
|
|
|
|
|
+
|
|
|
|
|
+ /deep/ div {
|
|
|
|
|
+ .ver(baseline);
|
|
|
|
|
+
|
|
|
|
|
+ .decimal {
|
|
|
|
|
+ .size(24rpx);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .original-price {
|
|
|
|
|
+ margin-left: 6rpx;
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: var(--bor-color1);
|
|
|
|
|
+ text-decoration: line-through;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .stat-value {
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- margin-right: 4rpx;
|
|
|
|
|
|
|
+ .sale_right {
|
|
|
|
|
+ .size(22rpx);
|
|
|
|
|
+ color: var(--text);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .stat-unit {
|
|
|
|
|
- font-size: 20rpx;
|
|
|
|
|
- color: var(--text-01);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .info_name {
|
|
|
|
|
+ .size(28rpx);
|
|
|
|
|
+ line-height: 48rpx;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: var(--text);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- .shop-tags {
|
|
|
|
|
- padding: 0 30rpx 20rpx;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 12rpx;
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
-
|
|
|
|
|
- .tag {
|
|
|
|
|
- font-size: 22rpx;
|
|
|
|
|
- color: var(--primary);
|
|
|
|
|
- background: rgba(255, 107, 107, 0.1);
|
|
|
|
|
- padding: 8rpx 16rpx;
|
|
|
|
|
- border-radius: 20rpx;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .shop-actions {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- padding: 0 30rpx 30rpx;
|
|
|
|
|
- gap: 20rpx;
|
|
|
|
|
-
|
|
|
|
|
- .action-btn {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- background: var(--light);
|
|
|
|
|
- padding: 24rpx 16rpx;
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
|
|
+ .service_wrapper {
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ background-color: var(--inputBg);
|
|
|
|
|
|
|
|
- .icon-font {
|
|
|
|
|
- font-size: 40rpx;
|
|
|
|
|
- color: var(--primary);
|
|
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .spec_title {
|
|
|
|
|
+ .size(28rpx);
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+ line-height: 60rpx;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- text {
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
|
|
+ .spec_info {
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ gap: 10rpx;
|
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
+ margin-top: 16rpx;
|
|
|
|
|
+ padding: 16rpx 0;
|
|
|
|
|
+ color: var(--text-02);
|
|
|
|
|
+ .size(24rpx);
|
|
|
|
|
+
|
|
|
|
|
+ .spec_item {
|
|
|
|
|
+ .ver();
|
|
|
|
|
+
|
|
|
|
|
+ .spec_value {
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ margin-left: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- .category-section,
|
|
|
|
|
- .products-section {
|
|
|
|
|
- padding: 0 30rpx 30rpx;
|
|
|
|
|
-
|
|
|
|
|
- .section-title {
|
|
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
- margin-bottom: 20rpx;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .scroll_item1 {
|
|
|
|
|
+ .detail_wrapper {
|
|
|
|
|
+ background-color: var(--light);
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ margin-top: 24rpx;
|
|
|
|
|
+
|
|
|
|
|
+ .module_title {
|
|
|
|
|
+ .size(28rpx);
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 60rpx;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .category-list {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 20rpx;
|
|
|
|
|
- overflow-x: auto;
|
|
|
|
|
- padding-bottom: 10rpx;
|
|
|
|
|
-
|
|
|
|
|
- .category-item {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- min-width: 120rpx;
|
|
|
|
|
- padding: 20rpx 16rpx;
|
|
|
|
|
- background: var(--light);
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
- border: 2rpx solid transparent;
|
|
|
|
|
-
|
|
|
|
|
- &.active {
|
|
|
|
|
- border-color: var(--primary);
|
|
|
|
|
- background: rgba(255, 107, 107, 0.05);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .desc_imgs {
|
|
|
|
|
+ .desc_cont {
|
|
|
|
|
+ /deep/ div {
|
|
|
|
|
+ div {
|
|
|
|
|
+ width: 100% !important;
|
|
|
|
|
+
|
|
|
|
|
+ div {
|
|
|
|
|
+ width: 100% !important;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ max-width: 100% !important;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: auto;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .category-icon {
|
|
|
|
|
- width: 48rpx;
|
|
|
|
|
- height: 48rpx;
|
|
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /deep/ img {
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .category-name {
|
|
|
|
|
- font-size: 22rpx;
|
|
|
|
|
- color: var(--black);
|
|
|
|
|
- text-align: center;
|
|
|
|
|
|
|
+ .spec_list {
|
|
|
|
|
+ .spec_item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ padding: 16rpx 0;
|
|
|
|
|
+ border-bottom: 1px solid var(--border);
|
|
|
|
|
+
|
|
|
|
|
+ .spec_label {
|
|
|
|
|
+ color: var(--text-02);
|
|
|
|
|
+ .size(24rpx);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .spec_value {
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+ .size(24rpx);
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- .products-grid {
|
|
|
|
|
- display: grid;
|
|
|
|
|
- grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
- gap: 20rpx;
|
|
|
|
|
|
|
+ .scroll_item2 {
|
|
|
|
|
+ padding: 24rpx 16rpx;
|
|
|
|
|
|
|
|
- .product-item {
|
|
|
|
|
- background: var(--light);
|
|
|
|
|
- border-radius: 16rpx;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
|
|
+ .title {
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 60rpx;
|
|
|
|
|
+ .size(28rpx);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .product-image {
|
|
|
|
|
|
|
+ .comment_item {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
- height: 200rpx;
|
|
|
|
|
- object-fit: cover;
|
|
|
|
|
|
|
+ margin-top: 16rpx;
|
|
|
|
|
+ padding: 12rpx;
|
|
|
|
|
+ border: 1px solid var(--border);
|
|
|
|
|
+ border-radius: 10rpx;
|
|
|
|
|
+ .comment_text {
|
|
|
|
|
+ margin-top: 6rpx;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .product-info {
|
|
|
|
|
- padding: 16rpx;
|
|
|
|
|
|
|
+ .tips {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .product-name {
|
|
|
|
|
- font-size: 24rpx;
|
|
|
|
|
|
|
+ .footer_btns {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ padding: 12rpx 24rpx;
|
|
|
|
|
+ background-color: var(--light);
|
|
|
|
|
+ .flex_center();
|
|
|
|
|
+ padding-bottom: calc(12rpx + env(safe-area-inset-bottom));
|
|
|
|
|
+ padding-bottom: calc(12rpx + constant(safe-area-inset-bottom));
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+
|
|
|
|
|
+ .btn_wrapper {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ .ver();
|
|
|
|
|
+ column-gap: 64rpx;
|
|
|
|
|
+
|
|
|
|
|
+ .btn {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ .size(28rpx);
|
|
|
|
|
+ height: 96rpx;
|
|
|
|
|
+ line-height: 28rpx;
|
|
|
|
|
+ padding: 8rpx 16rpx;
|
|
|
|
|
+ .flex_center();
|
|
|
|
|
+ border: 2px solid var(--black);
|
|
|
color: var(--black);
|
|
color: var(--black);
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
- display: -webkit-box;
|
|
|
|
|
- -webkit-line-clamp: 2;
|
|
|
|
|
- line-clamp: 2;
|
|
|
|
|
- -webkit-box-orient: vertical;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
|
|
+ border-radius: 20rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .product-price {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- margin-bottom: 8rpx;
|
|
|
|
|
-
|
|
|
|
|
- .current-price {
|
|
|
|
|
- font-size: 28rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: var(--red);
|
|
|
|
|
- margin-right: 8rpx;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .original-price {
|
|
|
|
|
- font-size: 20rpx;
|
|
|
|
|
- color: var(--text-01);
|
|
|
|
|
- text-decoration: line-through;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .btn_buy {
|
|
|
|
|
+ background-color: var(--light);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .product-sales {
|
|
|
|
|
- font-size: 20rpx;
|
|
|
|
|
- color: var(--text-01);
|
|
|
|
|
|
|
+ .btn_add {
|
|
|
|
|
+ background-color: var(--black);
|
|
|
|
|
+ color: var(--light);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|