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

2023-11-17

界面效果

【说明】

  • 界面中商品的图片来源于闲鱼,若侵权请联系删除
  • 关于商品分类页面的实现,请在我的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>

同项目其他文章

该项目的其他文章请查看【易售小程序项目】项目介绍、小程序页面展示与系列文章集合

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【易售小程序项目】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】 的相关文章

随机推荐

  • BurpSuite武器库打造之环境搭建和API介绍(上)

    0x00前言 在使用Burp Suite 以下简称Burp 来开展渗透工作的途中可能需要验证一些脑洞大开的想法 但Burp自带的功能可能无法满足你的需求 于是你迫切需要一个高度定制化的插件来实现这个功能 经查阅你得知除了Java还可以通过配
  • 无法清空剪切板,另一程序正在使用剪切板,无法复制东西了

    这种情况一般都是因为 有道或者其他翻译软件在你复制过程中不断把东西添加到剪切板中导致你无法继续添加新的东西到剪切板中 策略 关闭有道词典 在设置中将复制查词 取消即可
  • DBeaver连接MySQL提示“Public Key Retrieval is not allowed”的解决办法

    一 问题描述 一段时间没使用DBeaver 再次打开DBeaver连接MySQL提示 Public Key Retrieval is not allowed Public Key Retrieval is not allowed 不允许进行
  • HIVE简单介绍和了解

    用于解决海量日志数据的分析 hive是基于Hadoop的一个数据仓库工具 可以将结构化的数据文件映射为一张数据库表 并提供完整的sql查询功能 可以将sql语句转换为MapReduce任务进行运行 其优点是学习成本低 可以通过类SQL语句快
  • Linux开发工程师是吃青春饭的吗?

    Linux开发工程师怎么样 都说程序员是吃青春饭 Linux开发工作35岁之后还能做吗 坦白说 如果程序员在35岁的时候 工作经验 与刚毕业的时候差别不大 则其不可替代性就不高 很难在大龄时具备足够竞争力 大龄程序员 跟应该以专业洞识 理解
  • InterBase 6.5的新特性 (转)

    InterBase 6 5的新特性 转 more InterBase 6 5的新特性XML namespace prefix o ns urn schemas microsoft com Office office gt 作者 Bill T
  • Luat 功能开发教程(十四) 延时和定时器

    目录 延时和定时器 简介 API说明 实现流程 创建 消亡 自动消亡 手动消亡 判断定时器状态 知识拓展 示例 常见问题 相关资料以及购买链接 延时和定时器 简介 在luat脚本程序中 往往需要用到延时和等待等逻辑功能 例如 你想得到每隔3
  • 【el-time-picker设置默认值】Cannot read properties of undefined (reading ‘hour‘)

    需求 设置默认时间为2 0 0的时间选择器 产生报错的写法
  • 必填校验设置‘change‘, ‘blur‘同时起作用

    必填校验设置 change blur 同时起作用 rules seaAreaName required true message 请输入海区 trigger change blur
  • 华为机试-第二题

    查找知识图谱中的实例知识 知识图谱是一种结构化的语义网络 用于描述物理世界中的概念及其实例的相关关系 可以把知识图谱看成是一种有向图 图中的点是概念或实例 图中的边是概念及其实例的相关关系 现定义一种简单的知识图谱 概念 包括父概念及其子概
  • bootstrap jquery dataTable 异步ajax刷新表格数据

    异步请求 var postData env name new env name env url new env url env desc new env desc ajax type POST url test env add data p
  • Interactive Natural Language Processing

    本文是对 Interactive Natural Language Processing 的翻译 交互式自然语言处理 摘要 1 引言 2 交互式对象 2 1 人在环 2 2 KB在环 2 3 模型或工具在环 2 4 环境在环 3 交互界面
  • Oracle数据块概念及与行之间的关系测试

    数据块 Oracle Data Blocks 是Oracle最小的存储单位 Oracle数据存放在 块 中 一个块占用一定的磁盘空间 这里的 块 是Oracle的 数据块 不是操作系统的 块 操作系统的块通常为512k Oracle每次请求
  • openwrt 应用程序 开机自启动

    这几介绍一下openwrt 应用程序包开机自启动的两种方法 使用的平台是MTK7688开发板 首先写一个以及可以跑起来的工程 这里对工程就不做展开 以helloworld工程为例 helloworld工程写在 openwrt package
  • Python bs4怎么安装?

    bs4是BeautifulSoup4的简称 它是一个可以从HTML中提取数据的Python第三方库 具体来讲 bs4可以从茫茫的HTML代码中准确查找出你想要的内容 甚至一个小小的字符串 听起来是不是感觉bs4很厉害的样子 那么 Pytho
  • 预测模型的评价指标Matlab

    一般情况下 所要预测的数据分为连续型数据和离散性数据 连续型数据比如成绩分数 时间序列等 离散性数据通常为划分的分类标签 针对不同的数据类型 衡量模型的准确程度采用不同指标 如比较一些算法的准确率 若预测的数据为离散型 则算法的准确性自然容
  • 【综合转贴】CSS “点 ”“井号”的含义and ID class区别.

    body font family Arial sans serif color 333333 line height 1 166 margin 0px padding 0px masthead margin 0 padding 10px 0
  • 【3月比赛合集】45场可报名的数据挖掘奖金赛,任君挑选!

    CompHub 实时聚合多平台的数据类 Kaggle 天池 和OJ类 Leetcode 牛客 比赛 本账号同时会推送最新的比赛消息 欢迎关注 更多比赛信息见 CompHub主页 或 点击文末阅读原文 以下信息仅供参考 以比赛官网为准 目录
  • k8s部署之ETCD集群

    k8s部署之ETCD集群 1 etcd下载 etcd下载地址 https github com coreos etcd releases 从github etcd的发布页面选取相应的版本用 wget url 来下载 如 wget https
  • 【易售小程序项目】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】

    文章目录 界面效果 界面实现 工具js 页面 首页 让文字只显示两行 路由跳转传递对象 将商品分为两列显示 使用中划线划掉原价 后端 商品 controller service mapper sql 同项目其他文章 界面效果 说明 界面中商