【UniApp开发小程序】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】

news2025/2/14 3:26:46

文章目录

  • 界面效果
  • 界面实现
    • 工具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()">&#xe622;</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);
    ///设置每个商品的图片
    // 获取所有商品的id
    List<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">
      SELECT
      p.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 brandName
      FROM
      product AS p
      LEFT JOIN product_category AS pc ON p.product_category_id = pc.id
      LEFT JOIN brand AS b ON p.brand_id = b.id
      LEFT JOIN sys_user AS u ON p.user_id = u.user_id
      LEFT 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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/863809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM——Java 内存区域详解

文章目录 写在前面 (常见面试题)基本问题拓展问题 一 概述二 运行时数据区域2.1 程序计数器2.2 Java 虚拟机栈2.3 本地方法栈2.4 堆2.5 方法区2.5.1 方法区和永久代的关系2.5.2 常用参数2.5.3 为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢? 2.6 运行时常量池2.7 直…

DP(背包模型)

求方案数初始化总结 二维 1.体积至多是 j f[0][i]1 (0<i<m) 其余为 0 &#xff08;因为体积是至多是j 它可以小于j f[0][0]1 是肯定的 f[0][i] 这当中 i也可以包括0 一定要get到至多 即便不选物品 f[0][i]也是 1 它可以包含f[0][0]) 2.体积恰好是 j f[0][0]1 其余都…

MATLAB | 绘图复刻(十一) | 截断的含散点及误差棒的分组柱状图

hey大家好久不见&#xff0c;本期带来一篇绘图复刻&#xff0c;居然已经出到第11篇了&#xff0c;不知道有朝一日有没有机会破百&#xff0c;本期绘制的是《PNAS》期刊中pnas.2200057120文章的figure03&#xff0c;文章题目为Intranasal delivery of full-length anti-Nogo-A a…

SaaS BI数据可视化工具:免下载安装,登录即分析

之前有人问我&#xff0c;说&#xff1a;“BI数据可视化工具总是要下载安装&#xff0c;过程繁琐&#xff0c;没点IT基础的人也不太搞得定&#xff0c;有没有不用下载安装就能用的数据可视化工具&#xff1f;”答案当然是有的&#xff0c;那就是SaaS BI数据可视化工具。 SaaS …

并发——AQS原理以及AQS同步组件总结

文章目录 1 AQS 简单介绍2 AQS 原理2.1 AQS 原理概览2.2 AQS 对资源的共享方式2.3 AQS 底层使用了模板方法模式 3 Semaphore(信号量)-允许多个线程同时访问4 CountDownLatch &#xff08;倒计时器&#xff09;4.1 CountDownLatch 的两种典型用法4.2 CountDownLatch 的使用示例4…

生信豆芽菜-箱线图使用说明

网站&#xff1a;http://www.sxdyc.com/visualsBoxplot 一、使用方法 1.打开网址&#xff08;http://www.sxdyc.com/singleCollectionTool?href-diff&#xff09;&#xff0c;选择“箱线图”。 准备数据&#xff1a; 第一个文件为特征的表达文件&#xff0c;第一列为样本&am…

机器人CPP编程基础-05完结The End

非常不可思议……之前四篇博文竟然有超过100的阅读量…… 此文此部分终结&#xff0c;没有继续写下去的必要了。 插入一个分享&#xff1a; 编程基础不重要了&#xff0c;只要明确需求&#xff0c;借助AI工具就能完成一个项目。 当然也不是一次成功&#xff0c;工具使用也需要…

PP模块生产过程检验(工序检验)

质量检验是在一些情形下对物料进行检查的一个操作,用于检验物料是否符合标准。 1.常见检验类型: (1)进货检验(Incoming material Quality Check,IQC) (2) 生产过程检验(In Process Quality Check,IQPC) (3) 最终检验/产品检验(Final Quality Check,FQC) (4)出…

【产品应用】一体化步进伺服电机在自动液体处理工作站中的应用

随着工业自动化的快速发展&#xff0c;自动液体处理工作站在医药、食品、化工等领域中发挥着越来越重要的作用。一体化步进伺服电机作为一种高集成的驱动元件&#xff0c;具有高精度、高速度和高稳定性的特点&#xff0c;被广泛应用于自动液体处理工作站中。本文将详细介绍一体…

同源建模-build loop

对于有残基缺失的晶体结构往往采用同源建模的方式补全&#xff0c;但常规的同源建模方法往往造成非缺失区域残基的挪动&#xff0c;有时我们并不想出现这种状况&#xff0c;尤其是涉及到多个截短体拼合的情况&#xff0c;这时就需要用到约束性同源建模的方法&#xff0c;只对缺…

对一线大厂游戏测试员的访谈实录,带你了解游戏测试

今天采访了一个在游戏行业做测试的同学&#xff0c;他所在的游戏公司是做大型多人在线角色扮演类的游戏&#xff0c;类似传奇游戏。他所在的公司目前有1200多人&#xff0c;是上市公司&#xff0c;目前游戏产品在国内海外都有市场。 因为我是一个对游戏无感的人&#xff0c;所…

户外组网摆脱布线困扰,工业5G网关实现无人值守、远程实时监控

在物联网通信技术发达的2023&#xff0c;网络覆盖对所及之处的全面覆盖&#xff0c;科技发展的促使下很多高危户外场景也在思考如何利用无线技术提高人员安全及现场无人化管理。 煤矿是我们国家不可缺少的重要能源&#xff0c;其开采过程的危险系数也是众所皆知的&#xff0c;…

CANdelaStudio 使用介绍

CANdela Studio使用_哔哩哔哩_bilibili 一.CANdelaStudio使用tips 1.开始菜单打开软件&#xff0c;避免软件字体是德文的 2.打开软件之后&#xff0c;用“Open”打开.cdd或者.cddt文件&#xff0c;不要双击文件打开&#xff0c;这样容易报错 3.查看软件版本信息 4.只有Admin版…

CKA认证真题(3)-- 绝对干货!

目录 前言 15. sidecar边车容器 16. 升级集群 17.备份还原etcd 前言 17道真题难度等级 一级 rbac cpu 扩容 pod指定节点 pv pod日志 排障 查看可用节点 多容器pod 节点维护 二级 networkpolicy service ingress pvc 三级 sidecar 升级集群 备份还原etcd 本系列有三篇博客…

kettle simple-jndi 配置中心

jdbc.properties配置 SampleData/typejavax.sql.DataSource SampleData/driverorg.h2.Driver SampleData/urljdbc:h2:file:./samples/db/sampledb;IFEXISTSTRUE SampleData/userPENTAHO_USER SampleData/passwordPASSWORD SampleDataAdmin/typejavax.sql.DataSource SampleDat…

用于共享大文件的4种大文件传输工具和软件

个人或团队工作时&#xff0c;大文件传输软件和网站能够提升工作效率、有效地管理工作内容。由于疫情的影响&#xff0c;有时我们需要在家办公&#xff0c;在这种情况下&#xff0c;能够分享文件的工具就显得格外重要。 每个公司都需要一个文件传输软件&#xff0c;让员工可以…

Java 成功实现通过网址URL截图保存

Java 实现通过网址URL截图 1.DjNativeSwing方式 &#xff08;不好用&#xff09;2.phantomjs方式 &#xff08;截图还是有瑕疵&#xff09;3.selenium方式 &#xff08;满意&#xff0c;成功实现&#xff09;maven 引入下载相关浏览器chrome下载相关浏览器chromedriver驱动后端…

一文搞懂STP(从原理到配置)

一、STP出现的背景 1. 单点故障 如图9-1所示&#xff0c;PC1和PC2通过LSW1相互通信&#xff0c;如果LSW1出现了故障&#xff0c;那么PC1和PC2将不能相互通信&#xff0c;这种现象我们称之为单点故障。为了解决这个问题&#xff0c;我们提出了冗余的拓扑结构。 图9-1单点故障 …

【数据结构】单链表OJ题(一)

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、移除链表元素 &#x1f4a1;方法一&#xff1a; &#x1f4a1;方法二…

安卓如何快速定位native内存泄露。

步骤1&#xff09;cat /proc/pid/status,观察下面俩个指标 RssAnon: 5300 kB //一直增大说明匿名映射的内存增大&#xff0c;malloc本质就是调用匿名映射分 配内存 RssFile: 26884 kB //文件句柄泄露&#…