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

@@ -39,5 +39,17 @@ export function getArticleDetail(type) {
});
}
/**
* 分页获取文章列表(楼层装修用)
* @param params { pageNumber, pageSize, categoryId? }
*/
export function getArticleList(params) {
return http.request({
url: `/other/article`,
method: Method.GET,
params,
});
}

View File

@@ -193,6 +193,8 @@
<!-- <joinGroup v-if="item.type == 'joinGroup'" :res="item.options" /> -->
<integral v-if="item.type == 'integral'" :res="item.options" />
<coupon v-if="item.type == 'coupon'" :res="item.options" />
<articleList v-if="item.type == 'article'" :res="item.options" />
<shopList v-if="item.type == 'shop'" :res="item.options" />
<!-- <spike v-if="item.type == 'spike'" :res="item.options" /> -->
<blank v-if="item.type == 'blank'" :res="item.options" />
<lineLayout v-if="item.type == 'line'" :res="item.options" />
@@ -234,6 +236,8 @@ import lineLayout from '@/pages/tabbar/home/template/tpl_line.vue'
import richText from '@/pages/tabbar/home/template/tpl_rich_text.vue'
import integral from '@/pages/tabbar/home/template/tpl_integral.vue'
import coupon from '@/pages/tabbar/home/template/tpl_coupon.vue'
import articleList from '@/pages/tabbar/home/template/tpl_article.vue'
import shopList from '@/pages/tabbar/home/template/tpl_shop.vue'
import goodsTemplate from '@/components/m-goods-list/list.vue'
import { getStoreBaseInfo, getStoreCategory } from '@/api/store.js'
import {

View File

@@ -48,6 +48,8 @@
<richText v-if="item.type == 'richText'" :res="item.options" />
<integral v-if="item.type == 'integral'" :res="item.options" />
<coupon v-if="item.type == 'coupon'" :res="item.options" />
<articleList v-if="item.type == 'article'" :res="item.options" />
<shopList v-if="item.type == 'shop'" :res="item.options" />
</view>
<fetchCoupon ref="couponRef" />
</view>
@@ -88,6 +90,8 @@ import lineLayout from '@/pages/tabbar/home/template/tpl_line.vue'
import richText from '@/pages/tabbar/home/template/tpl_rich_text.vue'
import integral from '@/pages/tabbar/home/template/tpl_integral.vue'
import coupon from '@/pages/tabbar/home/template/tpl_coupon.vue'
import articleList from '@/pages/tabbar/home/template/tpl_article.vue'
import shopList from '@/pages/tabbar/home/template/tpl_shop.vue'
import { getFloorData } from '@/api/home'
const HOME_LAYOUT_PADDING_RPX = 16

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>

View File

@@ -48,6 +48,8 @@
<lineLayout v-if="item.type == 'line'" :res="item.options" />
<richText v-if="item.type == 'richText'" :res="item.options" />
<coupon v-if="item.type == 'coupon'" :res="item.options" />
<articleList v-if="item.type == 'article'" :res="item.options" />
<shopList v-if="item.type == 'shop'" :res="item.options" />
</div>
<u-no-network></u-no-network>
</div>
@@ -80,6 +82,8 @@ import lineLayout from '@/pages/tabbar/home/template/tpl_line'
import richText from '@/pages/tabbar/home/template/tpl_rich_text'
import integral from '@/pages/tabbar/home/template/tpl_integral'
import coupon from '@/pages/tabbar/home/template/tpl_coupon'
import articleList from '@/pages/tabbar/home/template/tpl_article'
import shopList from '@/pages/tabbar/home/template/tpl_shop'
import { toSpecial, getSpecial } from '@/api/home'
import permision from '@/js_sdk/wa-permission/permission.js'
import config from '@/config/config'