SpringBoot+Vue3 完成小红书项目

简介

该项目采用微服务架构,实现了前后端分离的系统设计。在前端,我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架,以提升开发效率和用户体验。而在后端,则是运用 SpringBoot 和 Mybatis-plus 进行开发,保证了系统的高效和稳定。此外,我们引入了 ElasticSearch 作为全文检索服务,以加快搜索速度和提高检索效率。同时,通过 WebSocket 技术实现了实时聊天和消息推送功能,增强了用户的互动体验。

代码下载

https://url21.ctfile.com/f/15432821-1020751544-c0e7e4?p=8418
(访问密码: 8418)

项目目录

  • yanhuo-web 前段页面
  • yanhuo-auth 认证服务
  • yanhuo-common 公共模块,存放一些工具类或公用类
  • yanhuo-platform 烟火 app 主要功能模块
  • yanhuo-im 聊天模块
  • yanhuo-search 搜索模块
  • yanhuo-util 第三方服务模块,邮箱短信,oss 对象存储服务
  • yanhuo-xo 对象存放模块

源码讲解

Controller 源码示例

首先来看 AlbumController 中的代码,主要讲解八个容易误解的方面。

  1. @RestController:这是一个组合注解,它表示这个类是一个控制器,并且其中的所有方法都会返回数据而不是视图。

  2. @RequestMapping(“/album”):这个注解用于将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上。在这里,它将所有的请求映射到以/album 为前缀的 URL。

  3. @Autowired:这个注解用于自动注入 Spring 容器中的 bean。在这里,它注入了一个 AlbumService 的实例,这个实例提供了专辑的增删改查操作。

  4. getAlbumPageByUserId 方法:这个方法用于根据用户 ID 获取专辑列表,并支持分页。它接受三个参数:当前页(currentPage),分页数(pageSize)和用户 ID(userId)。它调用 albumService 的 getAlbumPageByUserId 方法来获取数据,并返回一个 Result<?>对象。

  5. saveAlbumByDTO 方法:这个方法用于保存专辑。它接受一个 AlbumDTO 对象作为参数,并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后,它调用 albumService 的 saveAlbumByDTO 方法来保存专辑,并返回一个 Result<?>对象。

  6. getAlbumById 方法:这个方法用于根据专辑 ID 获取专辑。它接受一个 albumId 作为参数,并调用 albumService 的 getAlbumById 方法来获取数据,并返回一个 Result<?>对象。

  7. deleteAlbumById 方法:这个方法用于根据专辑 ID 删除专辑。它接受一个 albumId 作为参数,并调用 albumService 的 deleteAlbumById 方法来删除数据,并返回一个 Result<?>对象。

  8. updateAlbumByDTO 方法:这个方法用于更新专辑。它接受一个 AlbumDTO 对象作为参数,并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后,它调用 albumService 的 updateAlbumByDTO 方法来更新专辑,并返回一个 Result<?>对象。

package com.yanhuo.platform.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.validator.ValidatorUtils;
import com.yanhuo.common.validator.group.AddGroup;
import com.yanhuo.common.validator.group.UpdateGroup;
import com.yanhuo.platform.service.AlbumService;
import com.yanhuo.xo.dto.AlbumDTO;
import com.yanhuo.xo.entity.Album;
import com.yanhuo.xo.vo.AlbumVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/album")
@RestController
public class AlbumController {

    @Autowired
    AlbumService albumService;

    /**
     * 根据用户id获取专辑
     * @param currentPage 当前页
     * @param pageSize 分页数
     * @param userId 用户id
     * @return 专辑数
     */
    @RequestMapping("getAlbumPageByUserId/{currentPage}/{pageSize}")
    public Result<?> getAlbumPageByUserId(@PathVariable long currentPage, @PathVariable long pageSize,String userId){
        Page<Album> page =  albumService.getAlbumPageByUserId(currentPage,pageSize,userId);
        return Result.ok(page);
    }

    /**
     * 保存专辑
     * @param albumDTO 专辑实体
     * @return success
     */
    @RequestMapping("saveAlbumByDTO")
    public Result<?> saveAlbumByDTO(@RequestBody AlbumDTO albumDTO) {
        ValidatorUtils.validateEntity(albumDTO, AddGroup.class);
        albumService.saveAlbumByDTO(albumDTO);
        return Result.ok();
    }


    /**
     * 根据专辑id获取专辑
     * @param albumId 专辑id
     * @return 专辑实体
     */
    @RequestMapping("getAlbumById")
    public Result<?> getAlbumById(String albumId) {
        AlbumVo albumVo = albumService.getAlbumById(albumId);
        return Result.ok(albumVo);
    }

    /**
     * 根据专辑id删除专辑
     * @param albumId 专辑id
     * @return success
     */
    @RequestMapping("deleteAlbumById")
    public Result<?> deleteAlbumById(String albumId) {
        albumService.deleteAlbumById(albumId);
        return Result.ok();
    }

    /**
     * 更新专辑
     * @param albumDTO 专辑实体
     * @return success
     */
    @RequestMapping("updateAlbumByDTO")
    public Result<?> updateAlbumByDTO(@RequestBody AlbumDTO albumDTO) {
        ValidatorUtils.validateEntity(albumDTO, UpdateGroup.class);
        albumService.updateAlbumByDTO(albumDTO);
        return Result.ok();
    }
}

Service 源码示例

下面代码是一个服务实现类,用于处理与笔记相关的业务逻辑。这个类使用了 MyBatis-Plus 框架来简化数据库操作,并使用了 Hutool 工具类库来处理 JSON 数据。下面是这段代码的详细解释:

  1. NoteServiceImpl 类继承了 ServiceImpl<NoteDao, Note>,这意味着它继承了 MyBatis-Plus 提供的基本 CRUD 操作。NoteDao 是一个接口,用于定义与笔记相关的数据库操作方法。Note 是一个实体类,用于映射数据库中的笔记表。

  2. 类中注入了多个服务,包括用户服务、标签服务、分类服务、ES 客户端、关注服务、点赞或收藏服务以及 OSS 客户端。这些服务将在后面的方法中被使用。

  3. getNoteById 方法用于根据笔记 ID 获取笔记详情。该方法首先通过 getById 方法从数据库中获取笔记对象,然后将浏览次数加 1 并更新到数据库。接下来,通过用户 ID 获取用户对象,并将用户名、头像和更新时间设置到 NoteVo 对象中。然后,检查当前用户是否关注了该笔记的作者,并设置 NoteVo 对象的 isFollow 属性。接着,检查当前用户是否点赞或收藏了该笔记,并设置 NoteVo 对象的 isLikeisCollection 属性。最后,通过标签笔记关系服务获取该笔记的所有标签,并设置到 NoteVo 对象中。

  4. saveNoteByDTO 方法用于保存新的笔记。该方法首先从当前用户上下文中获取用户 ID,然后将传入的 JSON 字符串转换为 NoteDTO 对象,并将其转换为 Note 对象。然后,将用户 ID 设置到 Note 对象中,并保存到数据库。接下来,更新用户的动态数量。然后,处理标签关系,将标签 ID 和笔记 ID 保存到标签笔记关系表中。然后,通过 OSS 客户端上传图片,并将图片 URL 保存到 Note 对象中。最后,将 Note 对象更新到数据库,并将笔记信息添加到 ES 搜索引擎中。

  5. deleteNoteByIdsupdateNoteByDTOgetHotPage 方法目前没有实现具体的业务逻辑。这段代码的主要功能是处理与笔记相关的业务逻辑,包括获取笔记详情、保存新的笔记、更新笔记等。代码中使用了 MyBatis-Plus 框架来简化数据库操作,并使用了 Hutool 工具类库来处理 JSON 数据。此外,代码中还使用了 ES 搜索引擎和 OSS 对象存储服务来处理笔记的搜索和图片存储。

package com.yanhuo.platform.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanhuo.common.auth.AuthContextHolder;
import com.yanhuo.common.exception.YanHuoException;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.utils.ConvertUtils;
import com.yanhuo.platform.client.EsClient;
import com.yanhuo.platform.client.OssClient;
import com.yanhuo.platform.service.*;
import com.yanhuo.xo.dao.NoteDao;
import com.yanhuo.xo.dto.NoteDTO;
import com.yanhuo.xo.entity.*;
import com.yanhuo.xo.vo.NoteSearchVo;
import com.yanhuo.xo.vo.NoteVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class NoteServiceImpl extends ServiceImpl<NoteDao, Note> implements NoteService {
    @Autowired
    UserService userService;

    @Autowired
    TagNoteRelationService tagNoteRelationService;

    @Autowired
    TagService tagService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    EsClient esClient;

    @Autowired
    FollowerService followerService;

    @Autowired
    LikeOrCollectionService likeOrCollectionService;

    @Autowired
    OssClient ossClient;


    @Override
    public NoteVo getNoteById(String noteId) {
        Note note = this.getById(noteId);
        note.setViewCount(note.getViewCount() + 1);
        User user = userService.getById(note.getUid());
        NoteVo noteVo = ConvertUtils.sourceToTarget(note, NoteVo.class);
        noteVo.setUsername(user.getUsername())
                .setAvatar(user.getAvatar())
                .setTime(note.getUpdateDate().getTime());

        boolean follow = followerService.isFollow(user.getId());
        noteVo.setIsFollow(follow);

        String currentUid = AuthContextHolder.getUserId();
        List<LikeOrCollection> likeOrCollectionList = likeOrCollectionService.list(new QueryWrapper<LikeOrCollection>().eq("like_or_collection_id", noteId).eq("uid", currentUid));
        if(!likeOrCollectionList.isEmpty()) {
            Set<Integer> types = likeOrCollectionList.stream().map(LikeOrCollection::getType).collect(Collectors.toSet());
            noteVo.setIsLike(types.contains(1));
            noteVo.setIsCollection(types.contains(3));
        }

        //得到标签
        List<TagNoteRelation> tagNoteRelationList = tagNoteRelationService.list(new QueryWrapper<TagNoteRelation>().eq("nid", noteId));
        List<String> tids = tagNoteRelationList.stream().map(TagNoteRelation::getTid).collect(Collectors.toList());

        if (!tids.isEmpty()) {
            List<Tag> tagList = tagService.listByIds(tids);
            noteVo.setTagList(tagList);
        }

        this.updateById(note);
        return noteVo;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveNoteByDTO(String noteData, MultipartFile[] files) {
        String currentUid = AuthContextHolder.getUserId();
        NoteDTO noteDTO = JSONUtil.toBean(noteData, NoteDTO.class);
        Note note =ConvertUtils.sourceToTarget(noteDTO, Note.class);
        note.setUid(currentUid);
        boolean  save = this.save(note);
        if(!save){
            return null;
        }
        // TODO 需要往专辑中添加

        User user = userService.getById(currentUid);
        user.setTrendCount(user.getTrendCount() + 1);
        userService.updateById(user);

        List<String> tids = noteDTO.getTagList();
        List<TagNoteRelation> tagNoteRelationList = new ArrayList<>();

        String tags="";
        if(!tids.isEmpty()){
            for (String tid : tids) {
                TagNoteRelation tagNoteRelation = new TagNoteRelation();
                tagNoteRelation.setTid(tid);
                tagNoteRelation.setNid(note.getId());
                tagNoteRelationList.add(tagNoteRelation);
            }
            tagNoteRelationService.saveBatch(tagNoteRelationList);
            tags  = tagService.listByIds(tids).stream().map(Tag::getTitle).collect(Collectors.joining(","));
        }
        Category category = categoryService.getById(note.getCid());
        Category parentCategory = categoryService.getById(note.getCpid());

        List<String> dataList;
        try {
            Result<List<String>> result = ossClient.saveBatch(files, 1);
            dataList = result.getData();
        }catch (Exception e){
           throw new YanHuoException("添加图片失败");
        }
        String[] urlArr = dataList.toArray(new String[dataList.size()]);
        String urls = JSONUtil.toJsonStr(urlArr);
        note.setUrls(urls);
        note.setNoteCover(urlArr[0]);
        this.updateById(note);

        // 往es中添加数据
        NoteSearchVo noteSearchVo = ConvertUtils.sourceToTarget(note, NoteSearchVo.class);
        noteSearchVo.setUsername(user.getUsername())
                .setAvatar(user.getAvatar())
                .setLikeCount(0L)
                .setCategoryName(category.getTitle())
                .setCategoryParentName(parentCategory.getTitle())
                .setTags(tags)
                .setTime(note.getUpdateDate().getTime());
        esClient.addNote(noteSearchVo);
        return note.getId();
    }

    @Override
    public void deleteNoteByIds(List<String> noteIds) {

    }

    @Override
    public String updateNoteByDTO(NoteDTO noteDTO) {
        return null;
    }

    @Override
    public Page<NoteVo> getHotPage(long currentPage, long pageSize) {
        return null;
    }
}

Vue3 源码示例

这段代码是一个Vue3组件的模板和脚本部分,用于展示和加载关注者的动态(trends)。下面是对代码的详细解释:

模板部分(Template)
  1. <template> 标签内定义了组件的结构。
  2. 使用了Vue的v-infinite-scroll指令来实现无限滚动加载更多数据。
  3. 使用v-for指令循环渲染trendData数组中的每个动态项。
  4. 每个动态项包含用户头像、用户信息、动态内容、图片和交互按钮(点赞、评论等)。
  5. 使用v-ifv-else指令来条件渲染加载中的图片和已加载的图片。
  6. 事件绑定(@click)用于处理用户交互,如跳转到用户页面、点赞、查看动态等。
脚本部分(Script)
  1. 导入了必要的Vue组件和图标。
  2. 使用Vue 3的Composition API(<script setup>)定义组件的逻辑。
  3. 响应式变量,如currentPagepageSizetrendData等,用于控制分页和存储数据。
  4. handleLoad函数,用于处理图片加载完成的事件。
  5. toUser函数,用于导航到用户页面。
  6. getFollowTrends函数,用于获取关注者的动态数据。
  7. loadMoreData函数,用于加载更多动态数据。
  8. toMain函数,用于显示动态的详细内容。
  9. close函数,用于关闭动态详细内容的显示。
  10. refresh函数,用于刷新动态数据。
  11. like函数,用于处理点赞和取消点赞的操作。
    12.initData函数,用于初始化动态数据。
  12. 在组件挂载时调用initData函数。
样式部分(Style)
  1. 使用了Less预处理器编写样式。
  2. 定义了.container.trend-container.trend-item等类,用于设置组件的布局和样式。
  3. 使用了flex布局来排列用户头像、信息和图片。
  4. 使用了scoped属性,确保样式只应用于当前组件。
<template>
  <div class="container" v-infinite-scroll="loadMoreData">
    <ul class="trend-container">
      <li class="trend-item" v-for="(item, index) in trendData" :key="index">
        <a class="user-avatar">
          <img class="avatar-item" :src="item.avatar" @click="toUser(item.uid)" />
        </a>
        <div class="main">
          <div class="info">
            <div class="user-info">
              <a class>{{ item.username }}</a>
            </div>
            <div class="interaction-hint">
              <span>{{ item.time }}</span>
            </div>
            <div class="interaction-content" @click="toMain(item.nid)">
              {{ item.content }}
            </div>
            <div class="interaction-imgs" @click="toMain(item.nid)">
              <div class="details-box" v-for="(url, index) in item.imgUrls" :key="index">
                <el-image
                  v-if="!item.isLoading"
                  :src="url"
                  @load="handleLoad(item)"
                  style="height: 230px; width: 100%"
                >
                </el-image>
                <el-image
                  v-else
                  :src="url"
                  class="note-img animate__animated animate__fadeIn animate__delay-0.5s"
                  fit="cover"
                ></el-image>
              </div>
            </div>
            <div class="interaction-footer">
              <div class="icon-item">
                <i
                  class="iconfont icon-follow-fill"
                  style="width: 1em; height: 1em"
                  @click="like(item.nid, item.uid, index, -1)"
                  v-if="item.isLike"
                ></i>
                <i
                  class="iconfont icon-follow"
                  style="width: 1em; height: 1em"
                  @click="like(item.nid, item.uid, index, 1)"
                  v-else
                ></i
                ><span class="count">{{ item.likeCount }}</span>
              </div>
              <div class="icon-item">
                <ChatRound style="width: 0.9em; height: 0.9em" /><span class="count">{{
                  item.commentCount
                }}</span>
              </div>
              <div class="icon-item"><More style="width: 1em; height: 1em" /></div>
            </div>
          </div>
        </div>
      </li>
    </ul>
    <div class="feeds-loading">
      <Refresh style="width: 1.2em; height: 1.2em" color="rgba(51, 51, 51, 0.8)" />
    </div>
    <FloatingBtn @click-refresh="refresh"></FloatingBtn>
    <Main
      v-show="mainShow"
      :nid="nid"
      class="animate__animated animate__zoomIn animate__delay-0.5s"
      @click-main="close"
    ></Main>
  </div>
</template>
<script lang="ts" setup>
import { ChatRound, More, Refresh } from "@element-plus/icons-vue";
import { ref } from "vue";
import { getFollowTrendPage } from "@/api/follower";
import { formateTime } from "@/utils/util";
import FloatingBtn from "@/components/FloatingBtn.vue";
import Main from "@/pages/main/main.vue";
import type { LikeOrCollectionDTO } from "@/type/likeOrCollection";
import { likeOrCollectionByDTO } from "@/api/likeOrCollection";
import { useRouter } from "vue-router";

const router = useRouter();
const currentPage = ref(1);
const pageSize = ref(5);
const trendData = ref<Array<any>>([]);
const trendTotal = ref(0);
const topLoading = ref(false);
const mainShow = ref(false);
const nid = ref("");
const likeOrCollectionDTO = ref<LikeOrCollectionDTO>({
  likeOrCollectionId: "",
  publishUid: "",
  type: 0,
});

const handleLoad = (item: any) => {
  item.isLoading = true;
};

const toUser = (uid: string) => {
  router.push({ name: "user", state: { uid: uid } });
};

const getFollowTrends = () => {
  getFollowTrendPage(currentPage.value, pageSize.value).then((res) => {
    const { records, total } = res.data;
    console.log(records, total);
    records.forEach((item: any) => {
      item.time = formateTime(item.time);
      trendData.value.push(item);
    });
    trendTotal.value = total;
  });
};

const loadMoreData = () => {
  currentPage.value += 1;
  getFollowTrends();
};

const toMain = (noteId: string) => {
  nid.value = noteId;
  mainShow.value = true;
};

const close = (nid: string, isLike: boolean) => {
  const index = trendData.value.findIndex((item) => item.nid === nid);
  trendData.value[index].isLike = isLike;
  mainShow.value = false;
};

const refresh = () => {
  let scrollTop =
    window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  const clientHeight =
    window.innerHeight ||
    Math.min(document.documentElement.clientHeight, document.body.clientHeight);
  if (scrollTop <= clientHeight * 2) {
    const timeTop = setInterval(() => {
      document.documentElement.scrollTop = document.body.scrollTop = scrollTop -= 100;
      if (scrollTop <= 0) {
        clearInterval(timeTop);
        topLoading.value = true;
        setTimeout(() => {
          currentPage.value = 1;
          trendData.value = [];
          getFollowTrends();
          topLoading.value = false;
        }, 500);
      }
    }, 10); //定时调用函数使其更顺滑
  } else {
    document.documentElement.scrollTop = 0;
    topLoading.value = true;
    setTimeout(() => {
      currentPage.value = 1;
      trendData.value = [];
      getFollowTrends();
      topLoading.value = false;
    }, 500);
  }
};

const like = (nid: string, uid: string, index: number, val: number) => {
  likeOrCollectionDTO.value.likeOrCollectionId = nid;
  likeOrCollectionDTO.value.publishUid = uid;
  likeOrCollectionDTO.value.type = 1;
  likeOrCollectionByDTO(likeOrCollectionDTO.value).then(() => {
    trendData.value[index].isLike = val == 1;
    trendData.value[index].likeCount += val;
  });
};

const initData = () => {
  getFollowTrends();
};

initData();
</script>

<style lang="less" scoped>
.container {
  flex: 1;
  padding: 0 24px;
  padding-top: 72px;
  width: 67%;
  height: 100vh;
  margin: 0 auto;

  .feeds-loading {
    margin: 3vh;
    text-align: center;
  }

  .trend-container {
    .trend-item {
      display: flex;
      flex-direction: row;
      padding-top: 24px;
      max-width: 100vw;

      .user-avatar {
        margin-right: 24px;
        flex-shrink: 0;

        .avatar-item {
          width: 48px;
          height: 48px;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          border-radius: 100%;
          border: 1px solid rgba(0, 0, 0, 0.08);
          object-fit: cover;
        }
      }

      .main {
        flex-grow: 1;
        flex-shrink: 1;
        display: flex;
        flex-direction: row;
        padding-bottom: 12px;
        border-bottom: 1px solid rgba(0, 0, 0, 0.08);

        .info {
          flex-grow: 1;
          flex-shrink: 1;

          .user-info {
            display: flex;
            flex-direction: row;
            align-items: center;
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 4px;

            a {
              color: #333;
            }
          }
          .interaction-hint {
            font-size: 14px;
            color: rgba(51, 51, 51, 0.6);
            margin-bottom: 8px;
          }
          .interaction-content {
            display: flex;
            font-size: 14px;
            color: #333;
            margin-bottom: 12px;
            line-height: 140%;
            cursor: pointer;
          }

          .interaction-imgs {
            display: flex;
            .details-box {
              width: 25%;
              border-radius: 4px;
              margin: 8px 12px 0 0;
              cursor: pointer;

              .note-img {
                width: 100%;
                height: 230px;
                display: flex;
                border-radius: 4px;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                object-fit: cover;
              }
            }
          }

          .interaction-footer {
            margin: 8px 12px 0 0;
            padding: 0 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;

            .icon-item {
              display: flex;
              justify-content: left;
              align-items: center;
              color: rgba(51, 51, 51, 0.929);
              .count {
                margin-left: 3px;
              }
            }
          }
        }
      }
    }
  }
}
</style>

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

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

相关文章

JVM(2)实战篇

1 内存调优 1.1 内存溢出和内存泄漏 内存泄漏&#xff08;memory leak&#xff09;&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内存泄漏。 内存泄漏绝…

从汇编角度解释线程间互斥-mutex互斥锁与lock_guard的使用

多线程并发的竞态问题 我们创建三个线程同时进行购票&#xff0c;代码如下 #include<iostream> #include<thread> #include<list> using namespace std; //总票数 int ticketCount100; //售票线程 void sellTicket(int idx) {while(ticketCount>0){cou…

Pycharm里如何设置多Python文件并行运行

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 夕阳何事近黄昏&#xff0c;不道人间犹有未招魂。 大家好&#xff0c;我是皮皮。 一、前言 相信使用Pycharm的粉丝们肯定有和我一样的想法&#xff0c;…

Matplotlib自定义辅助函数 (一):让你的图表大放异彩!

Matplotlib美化秘诀&#xff1a;自定义辅助函数&#xff0c;让你的图表大放异彩&#xff01; 利用Matplotlib进行数据可视化示例 &#x1f335;文章目录&#x1f335; &#x1f333;一、创建自定义样式函数&#x1f333;&#x1f333;二、创建自定义颜色映射&#x1f333;&…

预处理详解(下)

1.#运算符 #运算符将宏的一个参数转换为字符串字面量。它仅允许出现在带参数的宏的替换列表中。 #运算符所执行的操作可以理解为”字符串化“。 例如&#xff1a; 我们将打印的字符串中的n改为参数n,这样在传参的时候就也会随着变化。假如我们不将其改为参数n的话会发生什么呢…

黑马Java——异常、File、综合案例

一、异常 误区&#xff1a;不是让我们以后不出异常&#xff0c;而是出现异常了之后&#xff0c;如何去处理 1、异常的分类 1.1、Error 1.2、Exception 1.3、小结 2、编译时异常和运行时异常 2.1、编译时异常 2.2、运行时异常 2.3、为什么异常要分成编译时异常和运行时异常&…

随机过程及应用学习笔记(三)几种重要的随机过程

介绍独立过程和独立增量过程。重点介绍两种独立增量过程-—维纳过程和泊松过程。 目录 前言 一、独立过程和独立增量过程 1、独立过程&#xff08;Independent Process&#xff09; 2、独立增量过程&#xff08;Independent Increment Process&#xff09; 二、正态过程&am…

【c++】构造函数(上)

Hello everybody!今天我们来聊一聊构造函数的用法和一些基本性质。内容比较多&#xff0c;我打算分两篇文章讲完&#xff01; 希望大家在看完我的文章后能够有所收获&#xff01; 1.构造函数的定义 构造函数是特殊的成员函数&#xff0c;需要注意的是&#xff0c;构造函数虽然…

Editable Scene Simulation for Autonomous Driving via Collaborative LLM-Agents

ChatSim&#xff1a;首个通过大语言模型实现可编辑逼真3D驾驶场景的仿真 论文链接&#xff1a;https://arxiv.org/pdf/2402.05746.pdf 代码链接&#xff1a;https://github.com/yifanlu0227/ChatSim 1. 摘要&#xff08;Abstract&#xff09; 自动驾驶中的场景仿真因其生成定制…

【前端高频面试题--git篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;前端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 前端高频面试题--git篇 常用命令git add 和 git stage 有什么区别怎么使用git连接到远程仓库git…

.target勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 网络安全威胁如勒索病毒已经成为企业和个人数据安全的重大挑战之一。.target勒索病毒作为其中的一种&#xff0c;以其高度复杂的加密算法和迅速变化的攻击手法备受关注。本文将深入介绍.target勒索病毒的特点&#xff0c;探讨如何有效地恢复被加密的数据文件…

【复现】某某ERP 信息泄露漏洞_49

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 该ERP基于SpringBoot框架和SaaS模式&#xff0c;立志为中小企业提供开源好用的ERP软件&#xff0c;目前专注进销存财务生产功能。…

模拟电子技术——基本放大电路

文章目录 前言一、三极管输入输出特性三极管放大作用三极管电流放大关系三极管的特性曲线 二、基本放大电路-电路结构与工作原理基本放大电路的构成基本放大电路放大原理三种基本放大电路比较 三、基本放大电路静态工作点什么是静态工作点&#xff1f;静态工作点的作用估算法分…

耳机壳UV树脂制作私模定制耳塞需要什么样的设备和技术?

制作私模定制耳塞需要使用到一些特定的设备和技术&#xff0c;包括但不限于以下内容&#xff1a; 耳模制作工具&#xff1a;用于获取用户耳型的耳模制作工具&#xff0c;如硅胶、橡皮泥等。需要使用熟练的手法和技术&#xff0c;确保耳模的准确性和稳定性。UV树脂&#xff1a;…

ARP请求的构造过程

ARP请求的构造过程&#xff1a; ARP请求的构造&#xff1a; 当设备A&#xff08;发起者&#xff09;想要与设备B&#xff08;目标&#xff09;通信&#xff0c;但它只知道设备B的IP地址&#xff08;例如&#xff0c;192.168.1.2&#xff09;&#xff0c;而不知道其MAC地址。设备…

Python数据科学:Scikit-Learn机器学习

4.1Scikit-Learn机器学习 Scikit-Learn使用的数据表示&#xff1a;二维网格数据表 实例1&#xff1a;通过Seaborn导入数据 def skLearn():scikit Learn基本介绍:return:import seaborn as sns#导入Iris数据集#注&#xff1a;一般网络访问不了iris sns.load_dataset(iris)ir…

Linux中alarm/setitimer函数(信号函数)

alarm函数 函数原型&#xff1a; unsigned int alarm(unsigned int seconds); 函数描述&#xff1a;设置定时器&#xff08;闹钟&#xff09;。在指定seconds后&#xff0c;内核会给当前进程发送 14&#xff09;SIGALRM信号。进程收到该信号&#xff0c;默认动作终止。每个进程…

MySQL 基础知识(四)之表操作

目录 1 约束 2 查看已有表 3 创建表 4 查看表结构 5 修改表 6 删除表 1 约束 主键约束 primary key&#xff1a;唯一&#xff0c;标识表中的一行数据&#xff0c;此列的值不可重复&#xff0c;且不能为 NULL&#xff0c;此外&#xff0c;可以多个列组成主键唯一约束 uniq…

GitHub项目推荐-InstantID

项目地址 https://github.com/InstantID/InstantID 项目简述 InstantID是一个图生图项目&#xff0c;仅仅通过一张正脸的图片&#xff0c;就能生成各种风格的人像。该项目的文档描述比较齐备&#xff0c;所以复现起来成本比较小。 项目截图 这是项目介绍中的一张截图&…

2023全球云计算市场份额排名

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 最近Synergy研究院发布了最新的全球云计算市场份额排名。 亚马逊依旧是以31%的的市场份额排名第一&#xff0c;微软azure24%排名第二&#xff0c;Google云11%排名第三&#xff0c;阿里云4%排名第四。腾讯云和IBM、…