feat(uniapp): 新增文章列表/店铺列表楼层组件

This commit is contained in:
pikachu1995@126.com
2026-10-12 10:31:31 +08:00
parent a108bb4d13
commit 40d42f001d
6 changed files with 195 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
<template>
<view class="tpl-article" :style="wrapperStyle" v-if="articleList.length">
<view class="article-title" v-if="title">{{ title }}</view>
<view
class="article-item"
v-for="item in articleList"
:key="item.id"
@click="goDetail(item)"
>
<view class="article-text">
<view class="article-name">{{ item.title }}</view>
<view class="article-time" v-if="item.createTime">{{ item.createTime.split(" ")[0] }}</view>
</view>
<image v-if="item.cover" class="article-thumb" :src="item.cover" mode="aspectFill" />
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { getArticleList } from "@/api/article.js";
const props = defineProps<{ res: any }>();
const articleList = ref<any[]>([]);
const title = computed(() => props.res?.list?.[0]?.title || "");
const count = computed(() => props.res?.list?.[0]?.count || 3);
const categoryId = computed(() => props.res?.list?.[0]?.categoryId || "");
const wrapperStyle = computed(() => ({
background: props.res?.bgColor || "#FFFFFF",
padding: `20rpx ${props.res?.paddingX ?? 0}rpx`,
marginBottom: `${props.res?.pageGap ?? 10}rpx`,
borderRadius: `${props.res?.borderRadius ?? 0}rpx`,
overflow: "hidden",
}));
onMounted(() => {
const params: any = { pageNumber: 1, pageSize: count.value };
if (categoryId.value) params.categoryId = categoryId.value;
getArticleList(params).then((res) => {
if (res.data.success && res.data.result) {
articleList.value = (res.data.result.records || []).slice(0, count.value);
}
});
});
function goDetail(item: any) {
uni.navigateTo({ url: `/pages/passport/article?id=${item.id}` });
}
</script>
<style lang="scss" scoped>
.article-title {
font-size: 30rpx;
font-weight: 600;
padding: 8rpx 24rpx 20rpx;
}
.article-item {
display: flex;
align-items: center;
padding: 16rpx 24rpx;
border-top: 2rpx solid #f5f5f5;
}
.article-text {
flex: 1;
min-width: 0;
}
.article-name {
font-size: 26rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.article-time {
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
}
.article-thumb {
width: 112rpx;
height: 84rpx;
border-radius: 8rpx;
margin-left: 20rpx;
flex-shrink: 0;
}
</style>

View File

@@ -0,0 +1,82 @@
<template>
<view class="tpl-shop" :style="wrapperStyle" v-if="shopList.length">
<view class="shop-title" v-if="title">{{ title }}</view>
<view class="shop-grid">
<view
class="shop-item"
v-for="item in shopList"
:key="item.id"
@click="goShop(item)"
>
<image class="shop-logo" :src="item.storeLogo" mode="aspectFill" />
<view class="shop-name">{{ item.storeName }}</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { getStoreList } from "@/api/store.js";
const props = defineProps<{ res: any }>();
const shopList = ref<any[]>([]);
const title = computed(() => props.res?.list?.[0]?.title || "");
const count = computed(() => props.res?.list?.[0]?.count || 4);
const wrapperStyle = computed(() => ({
background: props.res?.bgColor || "#FFFFFF",
padding: `20rpx ${props.res?.paddingX ?? 0}rpx`,
marginBottom: `${props.res?.pageGap ?? 10}rpx`,
borderRadius: `${props.res?.borderRadius ?? 0}rpx`,
overflow: "hidden",
}));
onMounted(() => {
getStoreList({ pageNumber: 1, pageSize: count.value }).then((res) => {
if (res.data.success && res.data.result) {
shopList.value = (res.data.result.records || []).slice(0, count.value);
}
});
});
function goShop(item: any) {
uni.navigateTo({ url: `/pages/product/shopPage?id=${item.id}` });
}
</script>
<style lang="scss" scoped>
.shop-title {
font-size: 30rpx;
font-weight: 600;
padding: 8rpx 24rpx 20rpx;
}
.shop-grid {
display: flex;
flex-wrap: wrap;
padding: 0 24rpx;
}
.shop-item {
width: 50%;
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.shop-logo {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
background: #f0f0f0;
flex-shrink: 0;
}
.shop-name {
font-size: 26rpx;
color: #333;
margin-left: 16rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>