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"; import { http } from "../util/api";
export const commonAPI = { export const commonAPI = {
getRegion: () => http.get('/regions/provinces'), getRegion: () => http.get('/common/provinces'),
} }
export default { 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 => { authAPI.login(loginData).then(response => {
console.log('登录结果', response); console.log('登录结果', response);
uni.clearStorageSync()
if (response.success) { if (response.success) {
// 激活用户 // 激活用户
uni.setStorageSync("token", response.token) uni.setStorageSync("token", response.token)

View File

@@ -1,11 +1,15 @@
<template> <template>
<view class="mall-container"> <view class="mall-container">
<u-navbar :is-fixed="false" title="商城好物" :background="{background: 'transparent' }" :border-bottom="false" back-icon-color="#fff" <u-navbar :is-fixed="false" title="商城好物" :background="{background: 'transparent' }" :border-bottom="false"
title-color="#fff"> 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> </u-navbar>
<view class="search"> <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>
<view class="menu-list"> <view class="menu-list">
@@ -22,140 +26,176 @@
</view> </view>
<view class="mall-list"> <view class="mall-list">
<u-waterfall v-model="mallList" ref="uWaterfall1"> <u-waterfall v-model="mallList" ref="mallListRef">
<template v-slot:left="{leftList}"> <template v-slot:left="{leftList}">
<view class="mall-item u-m-r-10" v-for="(item, index) in leftList" :key="index"> <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" <u-lazy-load threshold="-450" border-radius="10" :image="item.image"
:index="index"></u-lazy-load> :index="index"></u-lazy-load>
<view class="mall-title u-m-l-5 u-m-r-5"> <view class="mall-title u-m-l-5 u-m-r-5">
{{item.title}} {{item.name}}
</view> </view>
<view class="mall-price u-m-l-5 u-m-r-5"> <del class="u-m-l-5 u-m-r-5" style="white-space: nowrap;">{{item.price}}</del>
{{item.price}} <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>
<view class="mall-tag u-m-l-5 u-m-r-5"> <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>
<view class="mall-tag-text"> <view class="mall-tag-owner" v-if="pointsType(item.payment_methods)">
放心购 积分
</view> </view>
</view> </view>
<view class="mall-shop u-m-l-5 u-m-r-5"> <view class="mall-shop u-m-l-5 u-m-r-5">
{{item.shop}} {{item.category}}
</view> </view>
</view> </view>
</template> </template>
<template v-slot:right="{rightList}"> <template v-slot:right="{rightList}">
<view class="mall-item u-m-l-10" v-for="(item, index) in rightList" :key="index"> <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> :index="index"></u-lazy-load>
<view class="mall-title u-m-l-5 u-m-r-5"> <view class="mall-title u-m-l-5 u-m-r-5">
{{item.title}} {{item.name}}
</view> </view>
<view class="mall-price u-m-l-5 u-m-r-5"> <del class="u-m-l-5 u-m-r-5" style="white-space: nowrap;">{{item.price}}</del>
{{item.price}} <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>
<view class="mall-tag u-m-l-5 u-m-r-5"> <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>
<view class="mall-tag-text"> <view class="mall-tag-owner" v-if="pointsType(item.payment_methods)">
放心购 积分
</view> </view>
</view> </view>
<view class="mall-shop u-m-l-5 u-m-r-5"> <view class="mall-shop u-m-l-5 u-m-r-5">
{{item.shop}} {{item.category}}
</view> </view>
</view> </view>
</template> </template>
</u-waterfall> </u-waterfall>
<u-loadmore margin-top="20" :status="loadStatus"></u-loadmore>
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <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 params = ref({
const keyword = 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 menuList = ["全部商品", "精美服饰", "日用百货", "电子数码", "美妆饰品", "食物饮品"]
const currentMenu = ref(0) const currentMenu = ref(0)
const handleMenuChange = (val : number) => { const handleMenuChange = (val : number) => {
currentMenu.value = val currentMenu.value = val
menuCategoryMap(val)
reloadMallData()
} }
// 数据 // 上拉刷新
const mallList = ref([ onReachBottom(() => {
{ loadMallData()
price: 35, })
title: '北国风光,千里冰封,万里雪飘',
shop: '李白杜甫白居易旗舰店', onMounted(() => {
image: 'http://pic.sc.chinaz.com/Files/pic/pic9/202002/zzpic23327_s.jpg', loadMallData()
}, })
{
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',
},
])
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -244,6 +284,11 @@
font-size: 30rpx; font-size: 30rpx;
color: $u-type-error; color: $u-type-error;
margin-top: 10rpx; margin-top: 10rpx;
.icon {
height: 30rpx;
width: 30rpx;
}
} }
@@ -264,9 +309,9 @@
} }
.mall-tag-text { .mall-tag-text {
margin-right: 10px;
border: 1px solid $u-type-primary; border: 1px solid $u-type-primary;
color: $u-type-primary; color: $u-type-primary;
margin-left: 10px;
border-radius: 50rpx; border-radius: 50rpx;
line-height: 1; line-height: 1;
padding: 4rpx 14rpx; padding: 4rpx 14rpx;

View File

@@ -281,6 +281,7 @@
authAPI.register(registerData).then(response => { authAPI.register(registerData).then(response => {
if (response.success) { if (response.success) {
console.log('注册结果', response); console.log('注册结果', response);
uni.clearStorageSync()
uni.setStorageSync("token", response.token) uni.setStorageSync("token", response.token)
uni.setStorageSync("user", response.user) uni.setStorageSync("user", response.user)
uni.showToast({ 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版本 // 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 const TIMEOUT = 10000
// 初始化时设置token // 初始化时设置token
@@ -279,6 +279,7 @@ const handleError = (errorInfo) => {
export const http = { export const http = {
get: (url, params = {}, config = {}) => request({ get: (url, params = {}, config = {}) => request({
url, url,
params,
method: 'GET', method: 'GET',
...config ...config
}), }),

View File

@@ -3,3 +3,18 @@ export const validatePhone = (phone) => {
const reg = /^1[3-9]\d{9}$/; const reg = /^1[3-9]\d{9}$/;
return reg.test(phone); 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
}