【UniApp开发小程序】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】
文章目录
- 界面效果
- 界面实现
- 工具js
- 页面
- 首页
- 让文字只显示两行
- 路由跳转传递对象
- 将商品分为两列显示
- 使用中划线划掉原价
- 后端
- 商品
- controller
- service
- mapper
- sql
界面效果
【说明】
- 界面中商品的图片来源于闲鱼,若侵权请联系删除
- 关于商品分类页面的实现,请在我的Uniapp系列文章中寻找来查看
- 关于页面中悬浮按钮的实现,请在我的Uniapp系列文章中寻找来查看


界面实现
工具js
该工具类的作用是,给定一个图片的url地址,计算出图片的高宽比,计算高宽比的作用是让图片可以按照正常比例显示
/*** 获取uuid*/
export default {/*** 获取高宽比 乘以 100%*/getAspectRatio(url) {uni.getImageInfo({src: url,success: function(res) {let aspectRatio = res.height * 100.0 / res.width;// console.log("aspectRatio:" + aspectRatio);return aspectRatio + "%";}});},
}
页面
首页
<template><view class="content"><view style="display: flex;align-items: center;"><u-search placeholder="请输入商品名称" v-model="searchForm.keyword" @search="listProductVo" :showAction="false":clearabled="true"></u-search><text class="iconfont" style="font-size: 35px;" @click="selectCategory()"></text></view><u-row customStyle="margin-top: 10px" gutter="10" align="start" v-if="productList[0].length>0&&loadData==false"><u-col span="6" class="col" v-for="(data,index) in productList" :key="index"><view class="productVoItem" v-for="(productVo,index1) in data" :key="index1"@click="seeProductDetail(productVo)"><u--image v-if="productVo.picList!=null&&productVo.picList.length>0" :showLoading="true":src="productVo.picList[0]" width="100%" :height="getAspectRatio(productVo.picList[0])"radius="10" mode="widthFix"></u--image><!-- <u--image v-else :showLoading="true" :src="src" @click="click"></u--image> --><view class="productMes"><text class="productName">【{{productVo.name}}】</text><text>{{productVo.description==null?'':productVo.description}}</text></view><view style="display: flex;align-items: center;"><!-- 现价 --><view class="price">¥<text class="number">{{productVo.price}}</text>/{{productVo.unit}}</view><view style="width: 10px;"></view><!-- 原价 --><view class="originPrice">¥{{productVo.originalPrice}}/{{productVo.unit}}</view></view><view style="display: flex;align-items: center;"><u--image :src="productVo.avatar" width="20" height="20" shape="circle"></u--image><view style="width: 10px;"></view><view> {{productVo.nickname}}</view></view></view></u-col></u-row><u-empty v-if="productList[0].length==0&&loadData==false" mode="data" texColor="#ffffff" iconSize="180"iconColor="#D7DEEB" text="所选择的分类没有对应的商品,请重新选择" textColor="#D7DEEB" textSize="18" marginTop="30"></u-empty><view style="margin-top: 20px;" v-if="loadData==true"><u-skeleton :loading="true" :animate="true" rows="10"></u-skeleton></view><!-- 浮动按钮 --><FloatButton @click="cellMyProduct()"><u--image :src="floatButtonPic" shape="circle" width="60px" height="60px"></u--image></FloatButton></view>
</template><script>import FloatButton from "@/components/FloatButton/FloatButton.vue";import {listProductVo} from "@/api/market/prodct.js";import pictureApi from "@/utils/picture.js";export default {components: {FloatButton},onShow: function() {let categoryNameList = uni.getStorageSync("categoryNameList");if (categoryNameList) {this.categoryNameList = categoryNameList;this.searchForm.productCategoryId = uni.getStorageSync("productCategoryId");this.searchForm.keyword = this.getCategoryLayerName(this.categoryNameList);uni.removeStorageSync("categoryNameList");uni.removeStorageSync("productCategoryId");this.listProductVo();}},data() {return {title: 'Hello',// 浮动按钮的图片floatButtonPic: require("@/static/cellLeaveUnused.png"),searchForm: {// 商品搜索关键词keyword: "",productCategoryId: undefined},productList: [[],[]],loadData: false,}},onLoad() {},created() {this.listProductVo();},methods: {/*** 查询商品vo集合*/listProductVo() {this.loadData = true;listProductVo(this.searchForm).then(res => {this.loadData = false;// console.log("listProductVo:" + JSON.stringify(res))let productVoList = res.rows;this.productList = [[],[]];for (var i = 0; i < productVoList.length; i++) {if (i % 2 == 0) {// 第一列数据this.productList[0].push(productVoList[i]);} else {// 第二列数据this.productList[1].push(productVoList[i]);}}})},/*** 跳转到卖闲置页面*/cellMyProduct() {console.log("我要卖闲置");uni.navigateTo({url: "/pages/sellMyProduct/sellMyProduct"})},/*** 获取高宽比 乘以 100%*/getAspectRatio(url) {return pictureApi.getAspectRatio(url);},/*** 选择分类*/selectCategory() {uni.navigateTo({url: "/pages/sellMyProduct/selectCategory"})},/*** 获取商品名称*/getCategoryLayerName() {let str = '';for (let i = 0; i < this.categoryNameList.length - 1; i++) {str += this.categoryNameList[i] + '/';}return str + this.categoryNameList[this.categoryNameList.length - 1];},/*** 查看商品的详情*/seeProductDetail(productVo) {// console.log("productVo:"+JSON.stringify(productVo))uni.navigateTo({url: "/pages/product/detail?productVo=" + encodeURIComponent(JSON.stringify(productVo))})}}}
</script><style lang="scss">.content {padding: 20rpx;.col {width: 50%;}.productVoItem {margin-bottom: 20px;.productMes {overflow: hidden;text-overflow: ellipsis;display: -webkit-box;/* 显示2行 */-webkit-line-clamp: 2;-webkit-box-orient: vertical;.productName {font-weight: bold;}}.price {color: #ff0000;font-weight: bold;.number {font-size: 22px;}}.originPrice {color: #A2A2A2;font-size: 15px;// 给文字添加中划线text-decoration: line-through;}}}
</style>
让文字只显示两行
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
/* 显示2行 */
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;

路由跳转传递对象
因为首页已经查询到商品的很多信息了,点击查看商品详情的时候,很多信息不需要再查询一遍了,可以直接将商品的已知信息通过路由传递到新的页面去,需要注意的时候,将对象作为参数传递之前,需要先将对象进行编码
uni.navigateTo({url: "/pages/product/detail?productVo=" + encodeURIComponent(JSON.stringify(productVo))
})
将商品分为两列显示
首先将查询到的商品分为两组
let productVoList = res.rows;
this.productList = [[],[]
];
for (var i = 0; i < productVoList.length; i++) {if (i % 2 == 0) {// 第一列数据this.productList[0].push(productVoList[i]);} else {// 第二列数据this.productList[1].push(productVoList[i]);}
}
然后在布局中使用行列布局即可,即使用一行两列的方式来显示商品信息

使用中划线划掉原价

// 给文字添加中划线
text-decoration: line-through;
后端
商品
controller
/*** 查询商品Vo列表*/@PreAuthorize("@ss.hasPermi('market:product:list')")@PostMapping("/listProductVo")@ApiOperation("获取商品列表")public TableDataInfo listProductVo(@RequestBody ProductVo productVo) {startPage();if (productVo.getProductCategoryId() != null) {// --if-- 当分类不为空的时候,只按照分类来搜索productVo.setKeyword(null);}List<ProductVo> list = productService.selectProductVoList(productVo);return getDataTable(list);}
service
/*** 查询商品Vo列表** @param productVo* @return*/
@Override
public List<ProductVo> selectProductVoList(ProductVo productVo) {
// List<ProductVo> productVoList = new ArrayList<>();List<ProductVo> productVoList = baseMapper.selectProductVoList(productVo);///设置每个商品的图片// 获取所有商品的idList<Long> productIdList = productVoList.stream().map(item -> {return item.getId();}).collect(Collectors.toList());// 查询出所有商品的图片if (productIdList.size() > 0) {List<Picture> pictureList = pictureService.selectPictureListByItemIdListAndType(productIdList, PictureType.PRODUCT.getType());Map<Long, List<String>> itemIdAndPicList = new HashMap<>();for (Picture picture : pictureList) {if (!itemIdAndPicList.containsKey(picture.getItemId())) {List<String> picList = new ArrayList<>();picList.add(picture.getAddress());itemIdAndPicList.put(picture.getItemId(), picList);} else {itemIdAndPicList.get(picture.getItemId()).add(picture.getAddress());}}// 给每个商品设置图片for (ProductVo vo : productVoList) {vo.setPicList(itemIdAndPicList.get(vo.getId()));}}return productVoList;
}
mapper
void starNumDiffOne(@Param("productId") Long productId);
sql
<select id="selectProductVoList" parameterType="ProductVo" resultMap="ProductVoResult">SELECTp.id,p.NAME,p.description,p.original_price,p.price,p.product_category_id,pc.NAME AS productCategoryName,p.user_id,u.user_name as username,u.nick_name as nickname,u.avatar as avatar,p.reviewer_id,u1.user_name as reviewerUserName,p.fineness,p.unit,p.STATUS,p.is_contribute,p.functional_status,p.brand_id,b.NAME AS brandNameFROMproduct AS pLEFT JOIN product_category AS pc ON p.product_category_id = pc.idLEFT JOIN brand AS b ON p.brand_id = b.idLEFT JOIN sys_user AS u ON p.user_id = u.user_idLEFT JOIN sys_user AS u1 ON p.reviewer_id = u1.user_id<where><if test="keyword != null and keyword != ''">and p.name like concat('%', #{keyword}, '%')</if><if test="keyword != null and keyword != ''">or p.description like concat('%', #{keyword}, '%')</if><if test="productCategoryId != null and productCategoryId != ''">and p.product_category_id =#{productCategoryId}</if></where></select>
相关文章:
【UniApp开发小程序】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】
文章目录 界面效果界面实现工具js页面首页让文字只显示两行路由跳转传递对象将商品分为两列显示使用中划线划掉原价 后端商品controllerservicemappersql 界面效果 【说明】 界面中商品的图片来源于闲鱼,若侵权请联系删除关于商品分类页面的实现,请在我…...
Redis 持久化及集群架构
Redis 持久化及集群架构 本篇技术博文将深入探讨 Redis 持久化机制的原理、配置和使用方式。我们将介绍两种常用的持久化方式:RDB 持久化和 AOF 持久化。您将了解到它们的工作原理、优缺点以及如何根据需求选择合适的持久化方式。 通过深入学习 Redis 持久化及集群…...
FPGA + WS2812采灯控制
文章目录 一、WS2812C-2020-V11、产品概述2、引出端排列及功能3、数据传输时间4、数据传输方法 二、使用WS2812C显示图片1、静态显示2、动态显示 一、WS2812C-2020-V1 1、产品概述 WS2812C-2020-V1是一个集控制电路与发光电路于一体的智能外控LED光源;其外型采用最…...
【视频】使用OBS将MP4推流至腾讯云直播
1、下载OBS OBS官网:https://obsproject.com/ OBS支持Win、Mac、Linux,如果下载速度很慢,建议使用迅雷下载 2、OBS推流设置 2.1 添加场景 默认会有一个“场景”,如果想继续添加可以点击“+”按钮 2.2 添加媒体源 1)点击“来源”窗口中“+”按钮 2)支持的媒体源如…...
Vue基本知识
一、vue入门 Vue为前端的框架,免除了原生js的DOM操作。简化书写。 基于MVVM的思想,实现数据的双向绑定,使编程的重点放在数据上。 1、引入vue.js文件 2、定义vue核心对象,定义数据模型 3、编写视图 //1、引入vue.js <scr…...
item_get_sales-获取商品销量详情
一、接口参数说明: item_get_sales-获取商品销量详情,点击更多API调试,请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/taobao/item_get_sales 名称类型必须描述keyString是调用key(…...
LangChain手记 Memory
整理并翻译自DeepLearning.AILangChain的官方课程:Memory Memory 使用open ai的API调用GPT都是单次调用,所以模型并不记得之前的对话,多轮对话的实现其实是将前面轮次的对话过程保留,在下次对话时作为输入的message数组的一部分&…...
linux下安装.run后缀名文件
1.文件传输 对于大文件,不能直接拖拽,可以借助工具,例如WinSCP 创建会话时,需要提供虚拟机的主机名,可以采取输入ifconfig的命令,如图所示: ifconfig(接口配置)命令在 …...
Angular 性能优化实战
Angular 性能优化实战 Angular 是一个非常强大的前端框架,但是如果不注意性能优化,应用程序可能会变得非常慢并增加加载时间。 以下是一些Angular性能优化经验的实战建议: 1. 使用 OnPush 变更检测策略 默认情况下,Angular检查…...
在vue项目使用数据可视化 echarts ,柱状图、折线图、饼状图使用示例详解及属性详解
官网地址:Apache ECharts 一、下载插件并在页面中引入 npm install echarts --save 页面导入: import * as echarts from echarts 全局导入: main.js 中,导入并注册到全局 import echarts from echarts Vue.prototype.$echart…...
九耶丨阁瑞钛伦特-井字棋html5代码
你想了解关于井字棋(Tic-Tac-Toe)的HTML代码吗?以下是一个简单的井子棋的HTML代码示例: <!DOCTYPE html> <html> <head><title>Tic-Tac-Toe</title><style>.board {display: flex;flex-wrap…...
Linux服务器上配置HTTP和HTTPS代理
本文将向你分享如何在Linux服务器上配置HTTP和HTTPS代理的方法,解决可能遇到的问题,让你的爬虫项目顺利运行,畅爬互联网! 配置HTTP代理的步骤 1. 了解HTTP代理的类型:常见的有正向代理和反向代理两种类型。根据实际需求…...
OpenZFS 2.2 发布 RC3,支持 Linux 6.4
导读之前的 OpenZFS 2.2 候选版本已致力于实现与 Linux 6.4 内核的兼容性,而在 2.2-rc3 中,Linux 6.4 支持的元跟踪器已标记为已完成。 OpenZFS 2.2 发布了第 3 个 RC 版本。 之前的 OpenZFS 2.2 候选版本已致力于实现与 Linux 6.4 内核的兼容性&#x…...
嵌入式 C 语言程序数据基本存储结构
一、5大内存分区 内存分成5个区,它们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 1、栈区(stack):FIFO就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。 …...
记录VS2022离线安装NuGet包的过程
离线安装NuGet包主要分为两个阶段:指定安装源及下载包及其依赖项。本文记录在VS2022中离线安装NuGet包的过程及注意事项。 离线安装NuGet包,主要有两种方式:1)搭建局域网或本机NuGet服务器,将VS2022的源指定为NuGe…...
tomcat的多实例和动静分离
目录 多实例 安装tomcat 配置 tomcat 环境变量 修改server.xml文件 修改开关文件,添加环境变量 tomcat1 tomcat2 启动 浏览器访问测试 nginxtomcat实现动静分离 Nginx实现负载均衡的原理 部署nginx的负载器 搭建第三台tomcat 配置多实例服务器 Tomcat…...
点成案例丨比浊仪用于乳酸菌抑菌活性测定
乳酸菌概述 自1929年英国科学家弗莱明发现青霉素以来,抗生素为人类医学的进步做出了巨大贡献。然而,抗生素在临床上广泛且持续的使用导致病原微生物产生了耐药性。目前,病原微生物对抗生素的耐药性正在威胁人们的健康,寻找具有抑…...
总结synchronized
一.synchronized的特性 synchronized 是 Java 语言中内置的关键字,用于实现线程同步,以确保多线程环境下共享资源的安全访问。 互斥性:synchronized保证了同一时刻只有一个线程可以执行被synchronized修饰的代码块或方法。当一个线程进入sync…...
react实现模拟弹框遮罩的自定义hook
需求描述 点击按钮用于检测鼠标是否命中按钮 代码实现 import React from react; import {useState, useEffect, useRef} from react;// 封装一个hook用来检测当前点击事件是否在某个元素之外 function useClickOutSide(ref,cb) {useEffect(()>{const handleClickOutside…...
直接在html中引入Vue.js的cdn来实现一个简单的博客
摘要 其实建立一个博客系统是非常简单的,有很多开源的程序,如果你不喜欢博客系统,也可以自己开发,也可以自己简单做一个。我这次就是用Vue.js和php做后端服务实现一个简单的博客。 界面 代码结构 代码 index.html <!DOCTYP…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
iOS 项目怎么构建稳定性保障机制?一次系统性防错经验分享(含 KeyMob 工具应用)
崩溃、内存飙升、后台任务未释放、页面卡顿、日志丢失——稳定性问题,不一定会立刻崩,但一旦积累,就是“上线后救不回来的代价”。 稳定性保障不是某个工具的功能,而是一套贯穿开发、测试、上线全流程的“观测分析防范”机制。 …...
MySQL基本操作(续)
第3章:MySQL基本操作(续) 3.3 表操作 表是关系型数据库中存储数据的基本结构,由行和列组成。在MySQL中,表操作包括创建表、查看表结构、修改表和删除表等。本节将详细介绍这些操作。 3.3.1 创建表 在MySQL中&#…...
