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

文章目录

  • 界面效果
  • 界面实现
    • 工具js
    • 页面
      • 日期格式化
  • 后端
    • 收藏
      • Controller
      • Service
      • mapper
    • 评论
      • Controller
      • Service
      • Mapper
    • 商品
      • Controller
    • 阅读
      • Service

界面效果

【说明】

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

【商品详情】
在这里插入图片描述

【评论】
在这里插入图片描述

界面实现

工具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();
},

后端

收藏

Controller

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

在这里插入图片描述

/**
 * 收藏商品
 */
@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

需要注意的是,这里的树形结构只有两层数据(针对商品的评论为一层,针对评论的所有评论为一层),因为小程序不方便显示太多层数据,否则宽度会非常大,用户需要反复滑动来查看完整的评论
在这里插入图片描述

在这里插入图片描述

@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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【虫洞攻击检测】使用多层神经网络的移动自组织网络中的虫洞攻击检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Web网页浏览器远程访问jupyter notebook服务器【内网穿透】

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

zotero在不同系统的安装(win/linux)

1 window系统安装 zotero 官网&#xff1a; https://www.zotero.org/ 官方文档 &#xff1a;https://www.zotero.org/support/ (官方)推荐常用的插件: https://www.zotero.org/support/plugins 入门视频推荐&#xff1a; Zotero 文献管理与知识整理最佳实践 点击 exe文件自…

安全学习DAY17_信息打点-语言框架组件识别

信息打点-WEB打点-语言框架&开发组件 文章目录 信息打点-WEB打点-语言框架&开发组件本节涉及链接&工具本节知识&思维导图基础概念介绍框架&#xff1a;组件&#xff1a;Web架构 对应Web测试手法后端&#xff1a;前端组件&#xff1a;java居多&#xff0c;框架&…

物联网在制造业中的应用

制造业目前正在经历第四次工业革命&#xff0c;物联网、人工智能和机器人等技术进步正在推动行业的发展。研究表明&#xff0c;到2024年&#xff0c;全球制造商将在物联网解决方案上投资700亿美元&#xff0c;许多制造商正在实施物联网设备&#xff0c;以利用预测性维护和复杂的…

LeetCode450. 删除二叉搜索树中的节点

450. 删除二叉搜索树中的节点 文章目录 [450. 删除二叉搜索树中的节点](https://leetcode.cn/problems/delete-node-in-a-bst/)一、题目二、题解方法一&#xff1a;递归&#xff08;一种麻烦的方法&#xff09;方法二&#xff1a;优化后的递归 一、题目 给定一个二叉搜索树的根…

系统架构设计专业技能 · 信息安全技术

系列文章目录 系统架构设计专业技能 网络技术&#xff08;三&#xff09; 系统架构设计专业技能 系统安全分析与设计&#xff08;四&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构设计&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 …

C++入门知识点——解决C语言不足

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…

PgSQL中的DATE_PART使用

用法&#xff1a; DATE_PART(field, source) 这个DATE_PART()函数返回类型为double precision的值 century decade year month day hour minute second microseconds milliseconds dow doy epoch isodow isoyear timezone timezone_hour timezone_minute

扩散模型实战(四):从零构建扩散模型

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 本文以MNIST数据集为例&#xff0c;从…

【论文阅读】CONAN:一种实用的、高精度、高效的APT实时检测系统(TDSC-2020)

CONAN&#xff1a;A Practical Real-Time APT Detection System With High Accuracy and Efficiency TDSC-2020 浙江大学 Xiong C, Zhu T, Dong W, et al. CONAN: A practical real-time APT detection system with high accuracy and efficiency[J]. IEEE Transactions on Dep…

Spring Boot 知识集锦之actuator监控端点详解

文章目录 0.前言1.参考文档2.基础介绍默认支持的端点 3.步骤3.1. 引入依赖3.2. 配置文件3.3. 核心源码 4.示例项目5.总结 0.前言 背景&#xff1a; 一直零散的使用着Spring Boot 的各种组件和特性&#xff0c;从未系统性的学习和总结&#xff0c;本次借着这个机会搞一波。共同学…

超越函数界限:探索JavaScript函数的无限可能

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4da; 前言 &#x1f4d8; 1. 函数的基本概念 &#x1f4df; 1.1 函数的定义和调用 &#x1f4df; 1.2 …

化繁为简,使用Hibernate Validator实现参数校验

前言 在之前的悦享校园的开发中使用了SSM框架&#xff0c;由于当时并没有使用参数参数校验工具&#xff0c;方法的入参判断使用了大量的if else语句&#xff0c;代码十分臃肿&#xff0c;因此最近在重构代码时&#xff0c;将框架改为SpringBoot后&#xff0c;引入了Hibernate V…

57从零开始学Java之一文详解String字符串的底层实现原理

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在之前的两篇文章中&#xff0c;壹哥给大家介绍了String字符串及其常用的API方法、常用编码、正则表达…

第一讲:BeanFactory和ApplicationContext接口

BeanFactory和ApplicationContext接口 1. 什么是BeanFactory?2. BeanFactory能做什么&#xff1f;3.ApplicationContext对比BeanFactory的额外功能?3.1 MessageSource3.2 ResourcePatternResolver3.3 EnvironmentCapable3.4 ApplicationEventPublisher 4.总结 1. 什么是BeanF…

GuLi商城-前端基础Vue指令-单向绑定双向绑定

什么是指令? 指令 (Directives) 是带有 v- 前缀的特殊特性。 指令特性的预期值是:单个 JavaScript 表达式。 指令的职责是&#xff0c;当表达式的值改变时&#xff0c;将其产生的连带影响&#xff0c;响应式地作用于DOM 例如我们在入门案例中的 v-on&#xff0c;代表绑定事…

vscode + python

序 参考链接&#xff1a; 【教程】VScode中配置Python运行环境_哔哩哔哩_bilibili Python部分 Python Releases for Windows | Python.org vscode部分 Visual Studio Code - Code Editing. Redefined 一路next&#xff0c;全部勾上&#xff1a; 就可以了&#xff1a; 安装插…

盛元广通高校实验室开放预约与综合管理系统LIMS

系统概述&#xff1a; 高校实验室涉及到的课程、老师、学生多&#xff0c;管理起来费时费力&#xff0c;盛元广通高校实验室开放预约与综合管理系统LIMS提供简单易用的账号管理、实验室管理、课程管理、实验项目管理、实验时间设定&#xff1b;为学生提供简单易用的自主实验选…

设计模式篇---抽象工厂(包含优化)

文章目录 概念结构实例优化 概念 抽象工厂&#xff1a;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无须指定它们具体的类。 工厂方法是有一个类型的产品&#xff0c;也就是只有一个产品的抽象类或接口&#xff0c;而抽象工厂相对于工厂方法来说&#xff0c;是有…