2025-09-19

This commit is contained in:
2025-09-19 16:45:02 +08:00
parent 5b20f84f3d
commit d2a0584ee5
9 changed files with 172 additions and 98 deletions

View File

@@ -1,7 +1,7 @@
import { http } from "../util/api";
export const commonAPI = {
getRegion: () => http.get('/regions/provinces'),
getRegion: () => http.get('/common/provinces'),
}
export default {

11
api/mall.js Normal file
View File

@@ -0,0 +1,11 @@
import {
http
} from "../util/api";
export const mallAPI = {
getMallList: (params) => http.get('/mall', params)
}
export default {
mallAPI
}

View File

@@ -156,6 +156,7 @@
}
authAPI.login(loginData).then(response => {
console.log('登录结果', response);
uni.clearStorageSync()
if (response.success) {
// 激活用户
uni.setStorageSync("token", response.token)

View File

@@ -1,11 +1,15 @@
<template>
<view class="mall-container">
<u-navbar :is-fixed="false" title="商城好物" :background="{background: 'transparent' }" :border-bottom="false" back-icon-color="#fff"
title-color="#fff">
<u-navbar :is-fixed="false" title="商城好物" :background="{background: 'transparent' }" :border-bottom="false"
back-icon-color="#fff" title-color="#fff">
<template v-slot:right>
<image src="/static/icon/zhu.png" style="width: 50rpx;height: 50rpx;margin-right: 24rpx;" mode=""></image>
</template>
</u-navbar>
<view class="search">
<u-search placeholder="点击查询商品" v-model="keyword" :show-action="false" bg-color="#FEEFCE" </u-search>
<u-search @search="reloadMallData" placeholder="点击查询商品" v-model="params.keyword" :show-action="false"
bg-color="#FEEFCE" </u-search>
</view>
<view class="menu-list">
@@ -22,140 +26,176 @@
</view>
<view class="mall-list">
<u-waterfall v-model="mallList" ref="uWaterfall1">
<u-waterfall v-model="mallList" ref="mallListRef">
<template v-slot:left="{leftList}">
<view class="mall-item u-m-r-10" v-for="(item, index) in leftList" :key="index">
<u-lazy-load threshold="-450" border-radius="10" :image="item.image"
:index="index"></u-lazy-load>
<view class="mall-title u-m-l-5 u-m-r-5">
{{item.title}}
{{item.name}}
</view>
<view class="mall-price u-m-l-5 u-m-r-5">
{{item.price}}
<del class="u-m-l-5 u-m-r-5" style="white-space: nowrap;">{{item.price}}</del>
<view class="mall-price u-m-l-5 u-m-r-5" v-if="RDType(item.payment_methods)">
<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
{{item.rongdou_price}}
</view>
<view class="mall-price u-m-l-5 u-m-r-5" v-if="pointsType(item.payment_methods)">
<u-icon name="integral"></u-icon>
{{item.points_price}}
</view>
<view class="mall-tag u-m-l-5 u-m-r-5">
<view class="mall-tag-owner">
自营
<view class="mall-tag-text" v-if="RDType(item.payment_methods)">
融豆
</view>
<view class="mall-tag-text">
放心购
<view class="mall-tag-owner" v-if="pointsType(item.payment_methods)">
积分
</view>
</view>
<view class="mall-shop u-m-l-5 u-m-r-5">
{{item.shop}}
{{item.category}}
</view>
</view>
</template>
<template v-slot:right="{rightList}">
<view class="mall-item u-m-l-10" v-for="(item, index) in rightList" :key="index">
<u-lazy-load threshold="-450" border-radius="10" :image="item.image"
<u-lazy-load threshold="-450" border-radius="10" :image="getImageUrl(item.image_url)"
:index="index"></u-lazy-load>
<view class="mall-title u-m-l-5 u-m-r-5">
{{item.title}}
{{item.name}}
</view>
<view class="mall-price u-m-l-5 u-m-r-5">
{{item.price}}
<del class="u-m-l-5 u-m-r-5" style="white-space: nowrap;">{{item.price}}</del>
<view class="mall-price u-m-l-5 u-m-r-5" v-if="RDType(item.payment_methods)">
<image src="/static/icon/rongdou.png" class="icon" mode=""></image>
{{item.rongdou_price}}
</view>
<view class="mall-price u-m-l-5 u-m-r-5" v-if="pointsType(item.payment_methods)">
<u-icon name="integral"></u-icon>
{{item.points_price}}
</view>
<view class="mall-tag u-m-l-5 u-m-r-5">
<view class="mall-tag-owner">
自营
<view class="mall-tag-text" v-if="RDType(item.payment_methods)">
融豆
</view>
<view class="mall-tag-text">
放心购
<view class="mall-tag-owner" v-if="pointsType(item.payment_methods)">
积分
</view>
</view>
<view class="mall-shop u-m-l-5 u-m-r-5">
{{item.shop}}
{{item.category}}
</view>
</view>
</template>
</u-waterfall>
<u-loadmore margin-top="20" :status="loadStatus"></u-loadmore>
</view>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { ref, onMounted, computed } from 'vue';
import { onReachBottom } from '@dcloudio/uni-app'
import { mallAPI } from '../../api/mall';
import { getImageUrl } from '../../util/common';
// 关键词搜索
const keyword = ref('')
const params = ref({
keyword: '',
page: 1,
size: 5,
category: ''
})
const mallList = ref([])
const mallListRef = ref()
const loadStatus = ref('loadmore') // nomore
const maxPage = ref(1)
// 积分兑换
const pointsType = (val : any) => {
if (val && val.indexOf("points") >= 0) return true
return false
}
// 融豆兑换
const RDType = (val : any) => {
if (val && val.indexOf("rongdou") >= 0) return true
return false
}
// 加载数据
const loadMallData = () => {
if (loadStatus.value == 'nomore') return
mallAPI.getMallList(params.value).then((res) => {
mallList.value = mallList.value.concat(res.data.products)
maxPage.value = res.data.pagination.pages
params.value.page++
if (maxPage.value < params.value.page) {
loadStatus.value = 'nomore'
}
})
}
// 清空选项
const clearData = () => {
params.value = {
keyword: params.value.keyword,
page: 1,
size: 5,
category: ''
}
menuCategoryMap(currentMenu.value)
maxPage.value = 1
mallList.value = []
mallListRef.value.clear()
loadStatus.value = 'loadmore'
}
// 重新加载
const reloadMallData = () => {
clearData()
loadMallData()
}
// 菜单映射
const menuCategoryMap = (val) => {
switch (val) {
case 0:
params.value.category = ''
break
case 1:
params.value.category = '服装配饰'
break
case 2:
params.value.category = '日用百货'
break
case 3:
params.value.category = '数码产品'
break
case 4:
params.value.category = '美妆饰品'
break
case 5:
params.value.category = '食品饮料'
break
}
}
// 菜单
const menuList = ["全部商品", "精美服饰", "日用百货", "电子数码", "美妆饰品", "食物饮品"]
const currentMenu = ref(0)
const handleMenuChange = (val : number) => {
currentMenu.value = val
menuCategoryMap(val)
reloadMallData()
}
// 数据
const mallList = ref([
{
price: 35,
title: '北国风光,千里冰封,万里雪飘',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic.sc.chinaz.com/Files/pic/pic9/202002/zzpic23327_s.jpg',
},
{
price: 75,
title: '望长城内外,惟余莽莽',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic.sc.chinaz.com/Files/pic/pic9/202002/zzpic23325_s.jpg',
},
{
price: 385,
title: '大河上下,顿失滔滔',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic2.sc.chinaz.com/Files/pic/pic9/202002/hpic2119_s.jpg',
},
{
price: 784,
title: '欲与天公试比高',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic2.sc.chinaz.com/Files/pic/pic9/202002/zzpic23369_s.jpg',
},
{
price: 7891,
title: '须晴日,看红装素裹,分外妖娆',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic2.sc.chinaz.com/Files/pic/pic9/202002/hpic2130_s.jpg',
},
{
price: 2341,
shop: '李白杜甫白居易旗舰店',
title: '江山如此多娇,引无数英雄竞折腰',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg',
},
{
price: 661,
shop: '李白杜甫白居易旗舰店',
title: '惜秦皇汉武,略输文采',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23344_s.jpg',
},
{
price: 1654,
title: '唐宗宋祖,稍逊风骚',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23343_s.jpg',
},
{
price: 1678,
title: '一代天骄,成吉思汗',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23343_s.jpg',
},
{
price: 924,
title: '只识弯弓射大雕',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23343_s.jpg',
},
{
price: 8243,
title: '俱往矣,数风流人物,还看今朝',
shop: '李白杜甫白居易旗舰店',
image: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23343_s.jpg',
},
])
// 上拉刷新
onReachBottom(() => {
loadMallData()
})
onMounted(() => {
loadMallData()
})
</script>
<style scoped lang="scss">
@@ -244,6 +284,11 @@
font-size: 30rpx;
color: $u-type-error;
margin-top: 10rpx;
.icon {
height: 30rpx;
width: 30rpx;
}
}
@@ -264,9 +309,9 @@
}
.mall-tag-text {
margin-right: 10px;
border: 1px solid $u-type-primary;
color: $u-type-primary;
margin-left: 10px;
border-radius: 50rpx;
line-height: 1;
padding: 4rpx 14rpx;

View File

@@ -281,6 +281,7 @@
authAPI.register(registerData).then(response => {
if (response.success) {
console.log('注册结果', response);
uni.clearStorageSync()
uni.setStorageSync("token", response.token)
uni.setStorageSync("user", response.user)
uni.showToast({

BIN
static/icon/rongdou.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
static/icon/zhu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -1,7 +1,7 @@
// api.js - 适配uView3+uni-app版本
// 基础配置
const BASE_URL = 'http://192.168.1.43:3000/api'
const BASE_URL = 'http://192.168.1.55:5001/api'
const TIMEOUT = 10000
// 初始化时设置token
@@ -279,6 +279,7 @@ const handleError = (errorInfo) => {
export const http = {
get: (url, params = {}, config = {}) => request({
url,
params,
method: 'GET',
...config
}),

View File

@@ -1,5 +1,20 @@
// 校验
export const validatePhone = (phone) => {
const reg = /^1[3-9]\d{9}$/;
return reg.test(phone);
const reg = /^1[3-9]\d{9}$/;
return reg.test(phone);
};
export const getImageUrl = (imagePath) => {
if (!imagePath ) return ''
if (imagePath.startsWith('http')) return imagePath
// const baseURL = "http://192.168.1.43:3000"
// 如果图片路径以/uploads开头直接返回原路径
if (imagePath.startsWith('/uploads')) {
return `${imagePath}`
}
return fullUrl
}