【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】

这篇具有很好参考价值的文章主要介绍了【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

界面效果

【说明】

  • 界面中商品的图片来源于闲鱼,若侵权请联系删除

【商品详情】
【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】,小程序开发,uni-app,小程序,javascript,MYSQL递归查询

【评论】
【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】,小程序开发,uni-app,小程序,javascript,MYSQL递归查询

界面实现

工具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 + "%";
			}
		});
	},
}
export default {
	/**
	 * 日期格式化
	 */
	formatDateToString(date) {
	 return new Date(date).toLocaleString();
	},
}

页面

<template>
	<view class="container">
		<u-toast ref="uToast"></u-toast>
		<view class="userItem">
			<view class="userProfile">
				<u--image :src="productVo.avatar" width="35" height="35" shape="circle"></u--image>
				<view style="width: 10px;"></view>
				<view>
					<view class="nickname">{{productVo.nickname}}</view>
					<view class="other">10分钟前来过 广东工业大学大学城校区</view>
				</view>
			</view>
			<view class="follow" @click="follow" v-if="hadFollow==false">
				<view>
					<u-icon name="plus" color="#ffffff" style="font-weight: bold;" size="15"></u-icon>
				</view>
				<view style="margin-left: 10rpx;font-size: 15px;">
					关 注
				</view>
			</view>
			<view class="followed" @click="cancelFollow" v-else>
				<view style="font-size: 15px;color: #C2C2C2;">
					已 关 注
				</view>
			</view>
		</view>
		<view class="productItem">
			<view class="top">
				<view class="price">¥<text class="number">{{productVo.price}}</text>/{{productVo.unit}}</view>
				<view class="browseInformation">
					{{product.starNum}}人想要 | {{product.readNum}}个浏览
				</view>
			</view>
			<view class="productDetail">
				{{productVo.description}}
			</view>
			<u--image :showLoading="true" v-for="(pic,index) in productVo.picList" :src="pic" width="100%"
				:height="getAspectRatio(pic)" radius="10" mode="widthFix"></u--image>
		</view>

		<view class="commentView">
			<view style="color: #3D3D3D;">
				{{commentNum}}条评论
			</view>
			<view v-for="(commentItem,index) in commentVoList">
				<view class="commentItem">
					<view style="display: flex;">
						<u--image :src="commentItem.userAvatar" width="30" height="30" shape="circle"></u--image>
						<view style="width: 10px;"></view>
						<view @click="clickShowBottomPopup(1, commentItem.id,commentItem.userNickName)">
							<view class="nickname">{{commentItem.userNickName}}</view>
							<view class="content">
								{{commentItem.content}}
							</view>
							<view class="dateAndPosition">{{formatDateToString(commentItem.createTime)}}</view>
						</view>
					</view>
					<view style="display: inline-block;text-align: center;">
						<u-icon name="thumb-up" size="28" @click="likeComment(commentItem.id,commentItem)"
							v-if="commentItem.isLike==0"></u-icon>
						<u-icon name="thumb-up-fill" color="#2B92FF" size="28"
							@click="cancelLikeComment(commentItem.id,commentItem)" v-else></u-icon>
						<view style="font-size: 12px;color: #B9B9B9;">
							{{commentItem.likeNum}}
						</view>
					</view>

				</view>
				<view class="sonCommentItem" v-for="(commentItem1,index1) in commentItem.children">
					<view style="display: flex;">
						<u--image :src="commentItem1.userAvatar" width="30" height="30" shape="circle"></u--image>
						<view style="width: 10px;"></view>
						<view @click="clickShowBottomPopup(1, commentItem1.id,commentItem1.userNickName)">
							<view class="nickname">{{commentItem1.userNickName}}</view>
							<view class="content">
								<text style="font-size: 14px;">
									回复了<text style="color:#B9B9B9 ;">{{commentItem1.toUserNickName}}</text></text>
								<text>
									{{ commentItem1.content }}
								</text>
							</view>
							<view class="dateAndPosition">{{formatDateToString(commentItem1.createTime)}}</view>
						</view>
					</view>
					<view style="display: inline-block;text-align: center;">
						<u-icon name="thumb-up" size="28" @click="likeComment(commentItem1.id,commentItem1)"
							v-if="commentItem1.isLike==0"></u-icon>
						<u-icon name="thumb-up-fill" color="#2B92FF" size="28"
							@click="cancelLikeComment(commentItem1.id, commentItem1)" v-else></u-icon>
						<view style="font-size: 12px;color: #B9B9B9;">
							{{commentItem1.likeNum}}
						</view>
					</view>
				</view>

			</view>

		</view>

		<view class="footer">
			<view>
				<view class="item" @click="clickShowBottomPopup(0, productVo.id,)">
					<u-icon name="chat" size="28"></u-icon>
					<view class="comment">评论</view>
				</view>
				<view class="item" @click="starProduct()" v-if="hadStar==false">
					<u-icon name="star" size="28"></u-icon>
					<view class="comment">我想要</view>
				</view>
				<view class="item" @click="cancelStar()" v-if="hadStar==true">
					<u-icon name="star-fill" color="#2B92FF" size="28"></u-icon>
					<view class="comment" style="color: #2B92FF">已收藏</view>
				</view>
			</view>

			<view class="chat">
				<u-icon name="chat" color="#ffffff" size="18"></u-icon>
				<view style="width: 5px;"></view>
				私 聊
			</view>
		</view>

		<!-- 底部弹出框:用于输入评论 -->
		<!-- @close="this.showBottomPopup=false" 点击遮罩层关闭弹框  -->
		<u-popup :show="showBottomPopup" mode="bottom" :round="10" @close="this.showBottomPopup=false">
			<view class="commentPopup">
				<u--textarea v-model="comment.content" :placeholder="commentPlaceHolder" autoHeight height="200"
					border="surround"></u--textarea>
				<view class="commentButton" @click="commitComment()">
					<u-icon name="chat" color="#ffffff" size="18"></u-icon>
					<view style="width: 5px;"></view>
					评 论
				</view>
			</view>
		</u-popup>

	</view>
</template>

<script>
	import pictureApi from "@/utils/picture.js";
	import {
		addFollow,
		hadFollowSomeone,
		cancelFollowSomeone
	} from "@/api/market/follow.js";
	import {
		starProduct,
		cancelStar,
		hadStar
	} from "@/api/market/star.js";
	import {
		addComment,
		listCommentVoOfProduct
	} from "@/api/market/comment.js";
	import dateUtil from "@/utils/date.js";
	import {
		likeComment,
		cancelLikeComment
	} from "@/api/market/commentLike.js"
	import {
		getProduct
	} from "@/api/market/prodct.js"

	export default {
		data() {
			return {
				productVo: {},
				product: {},
				// 是否已经关注商品主人
				hadFollow: false,
				// 是否已经收藏商品
				hadStar: false,
				// 是否显示底部弹出框
				showBottomPopup: false,
				// 评论
				comment: {
					itemId: undefined,
					type: undefined,
					content: '',
					isTop: 0
				},
				// 存储商品对应的评论集合
				commentVoList: [],
				// 评论数量
				commentNum: undefined,
				commentPlaceHolder: "",
			}
		},
		methods: {
			/**
			 * 获取高宽比 乘以 100%
			 */
			getAspectRatio(url) {
				// uni.getImageInfo({
				// 	src: url,
				// 	success: function(res) {
				// 		let aspectRatio = res.height * 100.0 / res.width;
				// 		// console.log("aspectRatio:" + aspectRatio);
				// 		return aspectRatio + "%";
				// 	}
				// });
				return pictureApi.getAspectRatio(url);
			},
			/**
			 * 关注用户
			 */
			follow() {
				let data = {
					followedId: this.productVo.userId
				}
				addFollow(data).then(res => {
					this.hadFollow = true;
					this.$refs.uToast.show({
						type: 'success',
						message: "关注成功",
						duration: 300
					})
				}).catch(err => {
					this.$refs.uToast.show({
						type: 'error',
						message: err.msg,
						duration: 300
					})
				})
			},
			/**
			 * 取消关注
			 */
			cancelFollow() {
				cancelFollowSomeone(this.productVo.userId).then(res => {
					this.hadFollow = false;
					this.$refs.uToast.show({
						type: 'success',
						message: "取消关注成功",
						duration: 300
					})
				})
			},
			/**
			 * 查询是否已经关注了用户
			 */
			searchWhetherFollow() {
				hadFollowSomeone(this.productVo.userId).then(res => {
					// console.log("res:" + JSON.stringify(res));
					this.hadFollow = res.hadFollow;
					// console.log("this.hadFollow :" + this.hadFollow);
				})
			},
			/**
			 * 收藏商品
			 */
			starProduct() {
				starProduct(this.productVo.id).then(res => {
					this.hadStar = true;
					this.getProduct();
					this.$refs.uToast.show({
						type: 'success',
						message: "收藏成功",
						duration: 300
					})
				})
			},
			/**
			 * 取消收藏
			 */
			cancelStar() {
				cancelStar(this.productVo.id).then(res => {
					this.hadStar = false;
					this.getProduct();
					this.$refs.uToast.show({
						type: 'success',
						message: "取消收藏成功",
						duration: 300
					})
				})
			},
			/**
			 * 点赞评论
			 */
			likeComment(commentId, comment) {
				// console.log("comment:" + JSON.stringify(comment))
				likeComment(commentId).then(res => {
					comment.isLike = 1;
					comment.likeNum += 1;
					this.$refs.uToast.show({
						type: 'success',
						message: "点赞成功",
						duration: 300
					})
				})
			},
			/**
			 * 取消点赞评论
			 */
			cancelLikeComment(commentId, comment) {
				cancelLikeComment(commentId).then(res => {
					comment.isLike = 0;
					comment.likeNum -= 1;
					this.$refs.uToast.show({
						type: 'success',
						message: "取消点赞成功",
						duration: 300
					})
				})
			},
			/**
			 * 查询是否已经关注了用户
			 */
			searchWhetherStar() {
				hadStar(this.productVo.id).then(res => {
					// console.log("res:" + JSON.stringify(res));
					this.hadStar = res.hadStar;
					// console.log("this.hadFollow :" + this.hadFollow);
				})
			},
			/**
			 * 显示底部弹出框
			 */
			clickShowBottomPopup(type, itemId, username = undefined) {
				this.showBottomPopup = true;
				this.comment.type = type;
				this.comment.itemId = itemId;
				if (type == 0) {
					this.commentPlaceHolder = "想要了解更多信息,可以评论让商品主人看见哟";
				} else {
					this.commentPlaceHolder = "正在回复" + username + "";
				}
			},
			/**
			 * 发表评论
			 */
			commitComment() {
				// console.log("发送评论,comment:" + JSON.stringify(this.comment))
				addComment(this.comment).then(res => {
					this.showBottomPopup = false;
					this.comment.content = '';
					this.listCommentVoOfProduct();
					this.$refs.uToast.show({
						type: 'success',
						message: "评论发送成功",
						duration: 300
					})
				})
			},
			/**
			 * 获取商品对应的所有评论
			 */
			listCommentVoOfProduct() {
				listCommentVoOfProduct(this.productVo.id).then(res => {
					// console.log("listCommentVoOfProduct:" + JSON.stringify(res));
					this.commentVoList = res.tree;
					this.commentNum = res.commentNum;
				})
			},
			/**
			 * 格式化日期
			 * @param {Object} date
			 */
			formatDateToString(dateStr) {
				let date = new Date(dateStr);
				// 月份需要加一
				return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
			},
			/**
			 * 获取商品详细信息,同时增加阅读量
			 */
			getProduct() {
				getProduct(this.productVo.id).then(res => {
					console.log("product:" + JSON.stringify(res.data));
					this.product = res.data;
				})
			}
		},
		onLoad(e) {
			this.productVo = JSON.parse(decodeURIComponent(e.productVo));
			this.searchWhetherFollow();
			this.searchWhetherStar();
			this.listCommentVoOfProduct();
			this.getProduct();
			// console.log("productVo:" + JSON.stringify(productVo));
		}
	}
</script>

<style lang="scss">
	.container {
		// padding: 20rpx;
		background: #F7F7F7;

		.userItem {
			display: flex;
			align-items: center;
			justify-content: space-between;
			background: #ffffff;
			padding: 20rpx;

			.userProfile {
				display: flex;

				.nickname {
					color: #202020;
					font-weight: bold;
					font-size: 14px;
				}

				.other {
					color: #A6A4A5;
					font-size: 11px;
				}
			}

			.follow {
				display: flex;
				align-items: center;
				font-weight: bold;
				color: #ffffff;
				background: #2B92FF;
				border-radius: 20px;
				padding: 4px 8px;
			}

			.followed {
				background: #F6F6F6;
				border-radius: 20px;
				padding: 4px 8px;
			}
		}

		.productItem {
			background: #ffffff;
			padding: 20rpx;

			.top {
				display: flex;
				align-items: center;
				justify-content: space-between;

				.price {
					color: #F84442;
					font-weight: bold;

					.number {
						font-size: 30px;
					}
				}

				.browseInformation {
					color: #A6A4A5;
					font-size: 14px;
				}
			}

			.productDetail {
				margin-top: 20rpx;
				margin-bottom: 10rpx;
				color: #4C4C4C;
				font-size: 15px;
				line-height: 30px;
				font-weight: bold;
			}
		}

		.commentView {
			margin-top: 10px;
			// 用来预留展示 footer 的高度,不然footer会挡住评论
			margin-bottom: calc(60px + 10rpx);
			background: #ffffff;
			padding: 30rpx 30rpx;

			.nickname {
				font-size: 14px;
				color: #B9B9B9;
			}

			.content {
				margin: 5px;
				// 解决英文字符串、数字不换行的问题
				word-break: break-all;
				word-wrap: break-word;
			}

			.dateAndPosition {
				font-size: 11px;
				color: #B9B9B9;
			}

			.commentItem {
				display: flex;
				margin: 10px;
				justify-content: space-between;
			}

			.sonCommentItem {
				display: flex;
				margin: 10px 10px 10px 50px;
				justify-content: space-between;
			}

		}

		.footer {
			padding: 20rpx;
			position: fixed;
			// right: 20rpx;
			bottom: 0rpx;
			background: #ffffff;
			height: 60px;
			width: 710rpx;
			padding-top: 2px;

			display: flex;
			align-items: center;
			justify-content: space-between;

			.item {
				display: inline-block;
				text-align: center;
				margin-right: 10px;

				.comment {
					font-size: 10px;
				}
			}

			.chat {
				display: flex;
				align-items: center;
				background-color: #2B92FF;
				border-radius: 20px;
				padding: 7px;
				color: #ffffff;
				// margin-right: 20px;
				font-size: 12px;
			}

		}

		.commentPopup {
			display: flex;
			padding: 10px;
			min-height: 200rpx;

			.commentButton {
				background-color: #2B92FF;
				border-radius: 5px;
				padding: 7px;
				color: #ffffff;
				font-size: 12px;
				height: 20px;
				display: flex;
				align-items: center;
			}
		}


	}
</style>

日期格式化

有时候后端传递过来的日期格式直接在前端页面中展示不太美观或简洁,那就可以自己写一个日期格式化方法,将日期转化为我们需要的格式来显示

/**
 * 格式化日期
 * @param {Object} date
 */
formatDateToString(dateStr) {
	let date = new Date(dateStr);
	// 月份需要加一
	return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
},

英文自动换行显示

.content {
	margin: 5px;
	// 解决英文字符串、数字不换行的问题
	word-break: break-all;
	word-wrap: break-word;
}

后端

收藏

Controller

为了便于商品数据的查询,我在数据库设计的时候给商品表增加了收藏数的冗余字段,因此每次收藏商品或者取消商品的收藏的同时,需要更新商品表的收藏数

【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】,小程序开发,uni-app,小程序,javascript,MYSQL递归查询

/**
 * 收藏商品
 */
@PreAuthorize("@ss.hasPermi('market:star:star')")
@GetMapping("/starProduct/{productId}")
public AjaxResult starProduct(@PathVariable("productId") Long productId) {
    Star star = new Star();
    star.setUserId(getLoginUser().getUserId());
    star.setProductId(productId);
    boolean isStar = starService.addStar(star);
    if (isStar){
        // 需要将商品的收藏量+1
        productService.starNumPlusOne(productId);
    }
    return AjaxResult.success();
}

Service

package com.shm.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.Star;
import com.shm.mapper.StarMapper;
import com.shm.service.IStarService;
import org.springframework.stereotype.Service;

/**
* @author dam
* @description 针对表【collection(收藏表)】的数据库操作Service实现
* @createDate 2023-08-09 19:41:23
*/
@Service
public class IStarServiceImpl extends ServiceImpl<StarMapper, Star>
    implements IStarService {

    @Override
    public boolean addStar(Star star) {
        return baseMapper.addStar(star);
    }
}

mapper

public interface StarMapper extends BaseMapper<Star> {
    boolean addStar(@Param("star") Star star);
}

将商品添加收藏的时候,需要先判断同样的收藏数据不存在于数据库中才执行插入操作,否则如果用户网络卡顿并多次发送收藏请求,数据库会出现冗余的脏数据

<insert id="addStar">
    INSERT INTO `star` (`user_id`, `product_id`)
    SELECT #{star.userId},#{star.productId} FROM DUAL
    WHERE NOT EXISTS (
            SELECT 1 FROM `star`
            WHERE `user_id` = #{star.productId} AND `product_id` = #{star.productId} limit 1
        );
</insert>

评论

Controller

/**
 * 获取商品对应的所有评论
 *
 * @param productId
 * @return
 */
@PreAuthorize("@ss.hasPermi('market:comment:list')")
@GetMapping("/listCommentVoOfProduct/{productId}")
public AjaxResult listCommentVoOfProduct(@PathVariable("productId") Long productId) {
    // 查询出商品对应的所有评论数据
    List<CommentVo> commentVoList = commentService.listCommentVoOfProduct(productId, getLoginUser().getUserId());
    int commentNum = commentVoList.size();
    // 将评论数据封装成树形结构
    List<CommentVo> tree = commentService.buildTree(commentVoList);
    return AjaxResult.success().put("tree", tree).put("commentNum", commentNum);
}

Service

需要注意的是,这里的树形结构只有两层数据(针对商品的评论为一层,针对评论的所有评论为一层),因为小程序不方便显示太多层数据,否则宽度会非常大,用户需要反复滑动来查看完整的评论
【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】,小程序开发,uni-app,小程序,javascript,MYSQL递归查询

【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】,小程序开发,uni-app,小程序,javascript,MYSQL递归查询

@Override
public List<CommentVo> listCommentVoOfProduct(Long productId, Long userId) {
    return commentMapper.listCommentVoOfProduct(productId, userId);
}

/**
 * 将评论数据封装成树形结构
 *
 * @param commentVoList
 * @return
 */
@Override
public List<CommentVo> buildTree(List<CommentVo> commentVoList) {
    // 将所有父级评论过滤出来
    List<CommentVo> fatherList = commentVoList.stream().filter((item) -> {
        return item.getType() == 0;
    }).collect(Collectors.toList());
    commentVoList.removeAll(fatherList);
    // 为所有父级评论寻找孩子
    for (CommentVo father : fatherList) {
        father.setChildren(new ArrayList<>());
        this.searchSon(father.getId(), father.getUserNickName(), father.getChildren(), commentVoList);
    }
    return fatherList;
}

/**
 * 寻找孩子
 *
 * @param fatherId
 * @param children
 * @param commentVoList
 */
private void searchSon(Long fatherId, String fatherNickName, List<CommentVo> children, List<CommentVo> commentVoList) {
    for (CommentVo commentVo : commentVoList) {
        if (commentVo.getItemId().equals(fatherId)) {
            commentVo.setToUserNickName(fatherNickName);
            children.add(commentVo);
            this.searchSon(commentVo.getId(), commentVo.getUserNickName(), children, commentVoList);
        }
    }
}

Mapper

这段sql非常复杂,一次性将评论的主人昵称、头像、评论的点赞数量查出来了,同时还使用递归查询来不断查询出评论的子评论。我目前不能保证这段sql的效率,只是实现了功能,后面如果性能不足,我再想办法优化

<select id="listCommentVoOfProduct" resultType="com.ruoyi.common.core.domain.vo.CommentVo">
      SELECT
          ct.id,
          ct.user_id,
          ct.item_id,
          ct.type,
          ct.content,
          ct.create_time,
          u.nick_name AS userNickName,
          u.avatar AS userAvatar,
          CASE
              WHEN cl.user_id IS NULL THEN
                  0 ELSE 1
              END AS isLike,
          ct.LEVEL,
          COALESCE ( likeNum, 0 ) AS likeNum
      FROM
          (
              WITH RECURSIVE comment_tree AS (
                  SELECT
                      id,
                      user_id,
                      item_id,
                      type,
                      content,
                      create_time,
                      0 AS LEVEL
                  FROM
                      COMMENT
                  WHERE
                      item_id = #{productId} and type=0
                  UNION ALL
                  SELECT
                      c.id,
                      c.user_id,
                      c.item_id,
                      c.type,
                      c.content,
                      c.create_time,
                      ct.LEVEL + 1 AS LEVEL
                  FROM
                      COMMENT c
                          INNER JOIN comment_tree ct ON c.item_id = ct.id
                  WHERE
                      c.type = 1
              ) SELECT
                  *
              FROM
                  comment_tree
          ) ct
              LEFT JOIN ( SELECT comment_id, COUNT(*) AS likeNum FROM comment_like WHERE is_deleted = 0 GROUP BY comment_id ) pc ON ct.id = pc.comment_id
              LEFT JOIN sys_user AS u ON ct.user_id = u.user_id
              LEFT JOIN comment_like cl ON ct.id = cl.comment_id
              AND cl.user_id = #{userId} and cl.is_deleted =0
  </select>

商品

Controller

/**
 * 获取商品详细信息
 */
@PreAuthorize("@ss.hasPermi('market:product:query')")
@GetMapping(value = "/{id}")
@Transactional // 同时处理多个表,添加事务
public AjaxResult getInfo(@PathVariable("id") Long id) {
    // 首先判断用户有没有阅读该商品
    boolean isAdd = productReadService.addRead(new ProductRead(getLoginUser().getUserId(), id));
    if (isAdd) {
        // 需要将商品的阅读量+1
        productService.readNumPlusOne(id);
    }
    return success(productService.getById(id));
}

阅读

Service

<insert id="addRead">
    INSERT INTO `product_read` (`user_id`, `product_id`)
    SELECT #{productRead.userId},#{productRead.productId} FROM DUAL
    WHERE NOT EXISTS (
            SELECT 1 FROM `product_read`
            WHERE `user_id` = #{productRead.userId} AND `product_id` = #{productRead.productId} limit 1
        );

</insert>

同项目其他文章

该项目的其他文章请查看【易售小程序项目】项目介绍、小程序页面展示与系列文章集合文章来源地址https://www.toymoban.com/news/detail-654684.html

到了这里,关于【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Java+Vue+uniapp微信小程序商品展示系统设计和实现

    博主介绍 : ✌ 全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到哟 2022-2024年

    2024年02月06日
    浏览(32)
  • 多语言对接电商平台api接口获取京东商品评论数据代码展示示例

    商品评论接口的意义: 确认消费者关注与产品卖点是否一致; 洞察用户对价格、促销、直播的敏感度;发现产品质量、客服、物流等方面的问题;找到品牌宣称与用户预期、实际场景之间差异化;挖掘消费者偏好的差异性,进行用户分群偏好研究;还原客户故事,分析其购

    2024年02月11日
    浏览(26)
  • 从API到界面:如何将淘宝/天猫商品详情返回值转化为用户友好的展示

    在当今数字化时代,API(应用程序编程接口)已经成为连接不同服务和数据的桥梁。对于电商平台来说,API更是不可或缺的一部分。本文将以淘宝/天猫为例,探讨如何将API返回的商品详情数据转化为用户友好的展示形式。我们将通过代码示例来揭示这一过程。 1. API获取商品

    2024年02月19日
    浏览(28)
  • 在uni-app中使用sku插件,实现商品详情页规格展示和交互。

    学会使用插件市场,下载并使用 SKU 组件,实现 商品详情页 规格展示和交互。 SKU 概念 存货单位(Stock Keeping Unit),库存管理的最小可用单元,通常称为“单品”。 SKU 常见于电商领域,对于前端工程师而言,更多关注 SKU 算法 和 用户交互体验 。 uni-app 插件市场,是 uni-ap

    2024年01月19日
    浏览(33)
  • 【易售小程序项目】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】

    【说明】 界面中商品的图片来源于闲鱼,若侵权请联系删除 关于商品分类页面的实现,请在我的Uniapp系列文章中寻找来查看 关于页面中悬浮按钮的实现,请在我的Uniapp系列文章中寻找来查看 该工具类的作用是,给定一个图片的url地址,计算出图片的高宽比,计算高宽比的作

    2024年02月09日
    浏览(34)
  • 微信小程序开发(保姆式教程,点赞+收藏)

    二,微信开发者工具 下载微信web开发者工具,根据自己的操作系统下载对应的安装包进行安装即可。 新建项目 页面介绍 项目组成 page.json 文件 5,新建页面 文件用途 设置主页 把新建的文件路径调到最上面那就是主页了,意思就是,第一个路径就是首页的路径! 三,基本语法

    2024年02月22日
    浏览(45)
  • 【UniApp开发小程序】悬浮按钮+出售闲置商品+商品分类选择【后端基于若依管理系统开发】

    【悬浮按钮】 【闲置商品描述信息填写界面】 【商品分类选择界面】 【分类选择完成】 悬浮按钮漂浮于页面之上,等页面滑动时,悬浮按钮的位置相对于屏幕不会改变 【悬浮按钮组件】 【在其他界面中使用】 因为组件中使用了插槽,可以在该组件中插入其他组件 示例中

    2024年02月12日
    浏览(27)
  • 微信小程序python+vue今日菜谱美食点赞收藏评价系统

    谈到外出就餐,我们除了怕排队,也怕这家餐厅的服务员不够用,没人为我们点餐,那么一餐饭排队一小时,点餐恐怕也要花个半小时,这样不仅给消费者的用餐体验大打折扣同时也给商家的口碑造成了严重负面的影响,所以开发今日菜谱微信小程序系统是必须也是必然的。

    2024年02月11日
    浏览(32)
  • 微信小程序商品详情页(页面的实现)

    通过搜索页面传入的id,来进行操作(没有接口,都是假数据),页面如下 首先先把页面搭建起来,并进行渲染顶部导航栏已经做过现在就不发了,直接复制就好 页面信息的wxml 尾部导航栏wxml  js wxss 现在简单的小页面完成了

    2024年02月04日
    浏览(38)
  • 【UniApp开发小程序】私聊功能uniapp界面实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】

    本小程序在用户浏览首页的时候创建WebSocket连接,并将连接获得的WebSocket对象存储到全局变量中,方便其他页面来使用WebSocket 首先在项目的main.js文件中声明全局变量socket 对全局变量进行赋值 后续如果需要使用全局变量,直接使用 this.$socket 即可 下面的代码中有一个headbeat方

    2024年02月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包