Vue3实战Easy云盘(三):文件删除+文件移动+目录导航+上传优化/文件过滤/搜索

news2024/11/25 2:24:38

一、文件删除

(1)选中了之后才可以删除,没有选中时就显示暗调删除按钮
(2)实现选中高亮功能
(3)单个删除
(4)批量删除

Main.vue中 

                <!-- 按钮3 -->
                <!-- 如果selectFileIdList数组的长度为0(即数组为空),则HTML元素的disabled属性将被设置为true,从而使该元素变为禁用状态 -->
                <el-button type="danger" @click="delFileBatch" :disabled="selectFileIdList.length == 0">
                    <span class="iconfont icon-del"></span>
                    批量删除
                </el-button>

.....

<span class="iconfont icon-del" @click="delFile(row)">
                                    删除
</span>

......

// 定义多选文件夹列表
const selectFileIdList = ref([]);
// 多选
const rowSelected = (rows) => {
    // 重置为一个空数组,清空数据
    selectFileIdList.value = [];
    // 遍历 rows 数组中的每一个元素
    rows.forEach((item) => {
        // 经遍历到的fileId添加到selectFileIdList中
        selectFileIdList.value.push(item.fileId);
    });
};
// 删除单个文件
const delFile = (row) => {
    // 调用Confirm
    proxy.Confirm(
        `你确定要删除【$row.fileName】吗?删除的文件可在 10 天内通过回收站还原`,
        async () => {
            let result = await proxy.Request({
                url: api.delFile,
                params: {
                    fileIds: row.fileId,
                },
            });
            if (!result) {
                return;
            }
            // 重新获取数据
            loadDataList();
        }
    );
};
// 批量删除文件
const delFileBatch = () => {
    // 如果要删除的长度为0就不执行
    if (selectFileIdList.value.length == 0) {
        return;
    }
    // 调用Confirm
    proxy.Confirm(
        // 第一个参数是一个字符串,用于显示给用户的确认消息
        `你确定要删除这些文件吗?删除的文件可在 10 天内通过回收站还原`,
        // 第二个参数,当用户点击确认按钮后,这个异步函数会被执行
        async () => {
            // 使用await关键字调用proxy.Request方法,发送一个HTTP请求到服务器
            // 接收proxy.Request方法的响应并将其存储在result变量中
            let result = await proxy.Request({
                // 请求的URL来自api.delFile,这可能是一个常量或配置对象中的属性,指向删除文件的API端点。
                url: api.delFile,
                // join将这个数组转换为一个由逗号分隔的字符串(因为批量删除多个ids所以要分开),作为查询参数发送的文件ID列表
                params: {
                    fileIds: selectFileIdList.value.join(","),
                },
            });
            // 处理响应,
            if (!result) {
                return;
            }
            // 重新获取数据
            loadDataList();
        }
    );
};

 二、文件移动

(1)定义全局组件,FolderSelect.vue

(因为文件移动到哪个文件夹,文件保存到哪个文件夹都要用到,所以封装一个全局组件)

别忘记在Main.js中引入

src/components/FolderSelect.vue(不全面,未添加导航)

<!-- 移动/保存到哪个文件夹组件 -->
<template>
    <div>
        <!-- 弹出的对话框组件Dialog -->
        <Dialog
          :show="dialogConfig.show"
          :title="dialogConfig.title"
          :buttons="dialogConfig.buttons"
          width="600px"
          :showCancel="true"
          @close="dialogConfig.show = false">
            <!-- 目录导航 -->
            <div class="navigation-panel"></div>
            <!-- 文件夹列表 -->
            <div class="folder-list" v-if="folderList.length > 0">
                <!-- 每一项文件夹 -->
                <div
                   class="folder-item"
                   v-for="item in folderList"
                   @click="selectFolder(item)">
                   <!-- 文件类型为0时即文件夹就显示文件夹的图标 -->
                   <Icon :fileType="0"></Icon>
                   <!-- 每个文件夹的名字 -->
                   <span class="file-name">{{ item.fileName }}</span>
               </div>
            </div>
            <!-- 判断 -->
            <div v-else class="tips">
                移动到 <span>{{ currentFolder.fileName }}</span> 文件夹
            </div>
        </Dialog>
    </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance } from "vue";
import { useRouter, useRoute } from "vue-router";

const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();

const api = {
    loadAllFolder: "/file/loadAllFolder",
};

// 定义弹出框的属性
const dialogConfig = ref({
    show: false,
    // 对话框的标题
    title: "移动到",
    buttons: [
        {
            type: "primary",
            text: "移动到此",// 按钮上的文字
            // 当按钮被点击时触发的回调函数。在这个例子中,点击按钮会调用 folderSelect() 函数。
            click: (e) => {
                folderSelect();
            },
        },
    ],
});

// 目录列表
const folderList = ref([]);
// 父级ID
const filePid = ref("0");
// 当前目录ID
const currentFileIds = ref([]);
// 当前文件夹
const currentFolder = ref({});

// 获取所有的目录文件夹列表
const loadAllFolder = async () => {
    // API请求
    // 使用 await 等待 proxy.Request 方法的执行结果存储到result里
    let result = await proxy.Request({
        // 指定请求的url
        url: api.loadAllFolder,
        // 传递父id和当前文件夹id
        params: {
            filePid: filePid.value,
            currentFileIds: currentFileIds.value,
        },
    });
    // 判断结果
    if (!result) {
        return;
    }
    folderList.value = result.data;
};

// 展示弹出框对外的方法
const showFolderDialog = (currentFolder) => {
    dialogConfig.value.show = true;
    // 更新当前文件id数组
    currentFileIds.value = currentFolder;
    // 在加载一次获取到的目录文件夹列表
    loadAllFolder();
};

// 关闭弹出框
const close = () => {
    dialogConfig.value.show = false;
};
// 向外暴露这两个函数,使得父组件Main可以调用这两个函数
defineExpose({ showFolderDialog, close });

// 选择目录(目录导航)
const selectFolder = (data) => {
    navigationRef.value.openFolder(data);
};

// 确定选择要移动到的目录
// 将选定的文件目录参数传递给父组件 Main 中的 folderSelect 函数
const emit = defineEmits(["folderSelect"]);
// 此方法回调在父组件中
const folderSelect = () => {
    emit("folderSelect", filePid.value);
};

</script>

<style lang="scss" scoped>
.navigation-panel {
    padding-left: 10px;
    background: #f1f1f1;
}

.folder-list {
    .folder-item {
        cursor: pointer;
        display: flex;
        align-items: center;
        padding: 10px;

        .file-name {
            display: inline-block;
            margin-left: 10px;
        }

        &:hover {
            background: #f8f8f8;
        }
    }

    max-height: calc(100vh - 200px);
    min-height: 200px;
}

.tips {
    text-align: center;
    line-height: 200px;

    span {
        color: #06a7ff;
    }
}</style>

(2)Main.vue中调用

(不全面,未添加导航栏)

<!-- 引入组件 -->
        <FolderSelect
          ref="folderSelectRef"
          @folderSelect="moveFolderDone"
        ></FolderSelect>
// 移动目录
const folderSelectRef = ref();
// 当前要移动的文件(单个文件)
const currentMoveFile = ref({});
// 移动单个文件
const moveFolder = (data) => {
    // 存储当前要移动的单个文件的信息
    currentMoveFile.value = data;
    // 把当前文件id给showFolderDialog方法
    folderSelectRef.value.showFolderDialog(currentFolder.value.fileId);
};
// 移动批量文件
const moveFolderBatch = () => {
    // 清空当前要移动的文件数据
    currentMoveFile.value = {};
    // 把当前的文件夹id给showFolderDialog
    folderSelectRef.value.showFolderDialog(currentFolder.value.fileId);
};

// 点击按钮之后,移动文件操作
const moveFolderDone = async (folderId) => {
    // 如果要移动到当前目录,提醒无需移动
    if (
        // 如果当前移动的文件父级id等于此时要移动到的文件夹id或者当前文件夹的id等于要移动到的文件夹id
        currentMoveFile.value.filePid == folderId ||
        currentFolder.value.fileId == folderId
    ) {
        // 就提示无需移动
        proxy.Message.warning("文件正在当前目录,无需移动");
        return;
    }
    // 定义一个数组存放要移动的文件或者文件夹信息
    let fileIdsArray = [];
    // 如果是单个文件移动
    if (currentMoveFile.value.fileId) {
        // 就把当前移动的文件id传给这个数组
        fileIdsArray.push(currentMoveFile.value.fileId);
    } else {
        // 如果是多个文件移动
        // concat 连接多个数组
        // selectFileIdList 是指批量选择时选择的文件ID
        filedIdsArray = filedIdsArray.concat(selectFileIdList.value);
    }
    // 发请求并将结果存储
    let result = await proxy.Request({
        // 请求的url
        url: api.changeFileFolder,
        // 携带的参数
        params: {
            // 将 fileIdsArray 数组中的所有元素转换为一个由逗号分隔的字符串,赋值给fileIds
            fileIds: fileIdsArray.join(","),
            // 把folderId传到父文件id里面
            filePid: folderId,
        },
    });
    if (!result) {
        return;
    }
    // 调用子组件暴露的close方法,实现当前弹出框页面的关闭
    folderSelectRef.value.close();
    // 更新当前文件列表
    loadDataList();
};

三、目录导航(难点)

(1)导航栏组件(全局)

src/components/Navigation.vue
template结构

js
1.设置点击目录事件 openFolder:
2.暴露此事件供父组件使用:defineExpose({ openFolder });
3.设置当前路径 setpath:当点击后目录改变,路径也随之改变
4.获取当前路径的目录 getNavigationFolder
5.doCallback
6.监听路由
7.初始化设置init
8.setCurrentFolder 设置当前目录,点击导航跳转到所点击的目录
9.返回上一级 backParent

src/components/Navigation.vue

<template>
  <!-- 导航 -->
  <div class="top-navigation">
    <!-- 返回上一级 -->
    <template v-if="folderList.length > 0">
      <span class="back link" @click="backParent">返回上一级</span>
      <!-- 竖线 -->
      <el-divider direction="vertical" />
    </template>
    <!-- 全部文件:外面粗体的不能点 -->
    <span v-if="folderList.length == 0" class="all-file">全部文件</span>
    <!-- 全部文件:能点的 -->
    <span
      class="link"
      v-if="folderList.length > 0"
      @click="setCurrentFolder(-1)"
      >全部文件
    </span>
    <!-- 遍历文件列表 -->
    <template v-for="(item, index) in folderList">
      <!-- 图标 -->
      <span class="iconfont icon-right"></span>
      <!-- 文件名字可以点击 -->
      <span
        class="link"
        v-if="index < folderList.length - 1"
        @click="setCurrentFolder(index)"
        >{{ item.fileName }}
      </span>
      <!-- 文件名字不可以点击 -->
      <span class="text" v-if="index == folderList.length - 1">
          {{item.fileName}}
      </span>
    </template>
  </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, watch } from "vue";
import { useRouter, useRoute } from "vue-router";

const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();

// 定义父组件Main.vue传递过来的值
const props = defineProps({
  // 默认开启路由监听
  watchPath: {
    // 是否监听路由变化
    type: Boolean,
    default: true,
  },
  shareId: {
    type: String,
  },
  adminShow: {
    type: Boolean,
    default: false,
  },
});

const api = {
  // 首页 获取当前目录 获取列表 参数(path:完整路径)
  getFolderInfo: "/file/getFolderInfo",
  // 外部分享 获取目录信息 参数(shareId:分享id / path:完整路径)
  getFolderInfo4Share: "/showShare/getFolderInfo",
  // 管理员 获取当前目录 参数(path:完整路径)
  getFolderInfo4Admin: "/admin/getFolderInfo",
};

// 分类
const category = ref();
// 目录的集合
const folderList = ref([]);
// 当前目录
const currentFolder = ref({ fileId: "0" });

// 初始化
const init = () => {
  // 初始目录集合 设置为一个空数组
  folderList.value = [];
  // 初始当前目录设置
  currentFolder.value = { fileId: "0" };
  // 调用
  doCallback();
};

// 点击目录openFolder
// 父组件 Main/FolderSelect 中调用该方法,实现目录(文件及)的预览
const openFolder = (data) => {
  // 把data赋值给文件id和文件name
  const { fileId, fileName } = data;
  // 定义folder
  const folder = {
    fileName: fileName,
    fileId: fileId,
  };
  // 把folder push进目录集合
  folderList.value.push(folder);
  // 更新当前目录
  currentFolder.value = folder;
  // 设置当前路径,当点击后目录改变,路径也随之改变,调用setPath
  setPath();
};
defineExpose({ openFolder });

// 返回上一级
const backParent = () => {
  // 查找当前文件夹的索引
  let currentIndex = null;
  for (let i = 0; i < folderList.value.length; i++) {
    if (folderList.value[i].fileId == currentFolder.value.fileId) {
      currentIndex = i;
      break;
    }
  }
  // 设置当前文件夹为上一级目录
  setCurrentFolder(currentIndex - 1);
};

// 点击导航 设置当前目录(点击目录,跳转到所点击的目录)
const setCurrentFolder = (index) => {
  // 如果点的是全部文件
  if (index == -1) {
    // 初始化数组
    currentFolder.value = { fileId: "0" };
    folderList.value = [];
  } else {
    // 当前目录的值更新为目录集合数组为index的值
    currentFolder.value = folderList.value[index];
    // 删除从index+1开始的长度为目录集合数组的长度 的数组
    // 对于 splice(start, deleteCount, ...items) 方法:
    //  start(必需):开始更改数组的位置的索引。
    // deleteCount(必需):要删除的元素数量。如果设置为 0,则不会删除任何元素。
    // ...items(可选):要添加到数组中的新元素
    folderList.value.splice(index + 1, folderList.value.length);
  }
  setPath();
};

// 设置当前路径,当点击后目录改变,路径也随之改变
const setPath = () => {
  if (!props.watchPath) {
    // 设置不监听路由回调方法
    doCallback();
    return;
  }
  // 定义路径数组
  let pathArray = [];
  // 遍历目录集合的每一项
  folderList.value.forEach((item) => {
    // 把每一项的fileId push 到 路径数组里
    pathArray.push(item.fileId);
  });
  // 设置路由
  router.push({
    // 当前路径path
    path: route.path,
    // 参数
    query:
    // 如果pathArray长度为0,参数就为空,否则就把路径用/隔开加入到pathArray里面,更新path,添加到参数里面
      pathArray.length == 0
        ? ""
        : {
            path: pathArray.join("/"),
          },
  });
};

// 获取当前路径的目录
const getNavigationFolder = async (path) => {
  // 根据给定的 path 和一些其他属性(如 props.shareId 和 props.adminShow)来确定请求哪个 API,然后发送一个请求来获取该路径下的目录信息,并将获取到的目录信息存储在 folderList.value 中。
  let url = api.getFolderInfo;
  if (props.shareId) {
    url = api.getFolderInfo4Share;
  }
  if (props.adminShow) {
    url = api.getFolderInfo4Admin;
  }

  let result = await proxy.Request({
    url: url,
    showLoading: false,
    params: {
      path: path,
      shareId: props.shareId,
    },
  });
  if (!result) {
    return;
  }
  folderList.value = result.data;
};

// 回调 将当前的参数传递给父组件 Main
// 定义了一个名为 navChange 的事件。这允许子组件在需要时触发这个事件,并传递一些数据给父组件。
const emit = defineEmits(["navChange"]);
const doCallback = () => {
  emit("navChange", {
    categoryId: category.value,
    curFolder: currentFolder.value,
  });
};

// 监听路由
watch(
  () => route,
  // 它会在route的值变化时被调用。
  // newVal是route的新值,oldVal是route的旧值
  (newVal, oldVal) => {
    if (!props.watchPath) {
      return;
    }
    if (
      // 如果不在main路径里面就不用管
      newVal.path.indexOf("/main") === -1 &&
      newVal.path.indexOf("/settings/fileList") === -1 &&
      newVal.path.indexOf("/share") === -1
    ) {
      return;
    }
    // 把新携带的路径赋值给path,可以拿到?后面的一坨,query参数是?后面的一截
    const path = newVal.query.path;
    // params是route路由,category是在router里面定义的
    const categoryId = newVal.params.category;
    category.value = categoryId;
    if (path == undefined) {
      // 调用
      init();
    } else {
      // 调用
      getNavigationFolder(path);
      // 刷新的时候要把当前目录设置进来
      // 使用split("/")方法将path字符串分割为一个数组pathArray
      let pathArray = path.split("/");
      // fileId被赋值给currentFolder.value
      currentFolder.value = {
        // 它使用数组的最后一个元素(即path中的最后一个部分)作为fileId
        fileId: pathArray[pathArray.length - 1],
      };
      doCallback();
    }
  },
  { immediate: true, deep: true }
);
</script>

<style lang="scss" scoped>
.top-navigation {
  font-size: 13px;
  display: flex;
  align-items: center;
  line-height: 40px;
  .all-file {
    font-weight: bold;
  }
  .link {
    color: #06a7ff;
    cursor: pointer;
  }
  .icon-right {
    color: #06a7ff;
    padding: 0px 5px;
    font-size: 13px;
  }
}
</style>

(2)main.js中引入

import Navigation from '@/components/Navigation.vue';
app.component('Navigation', Navigation);

(3)Main.vue中使用组件

<!-- 导航 -->
<Navigation ref="navigationRef" @navChange="navChange"></Navigation>

Main.vue中绑定点击事件
 

<span @click="preview(row)">{{ row.fileName }}</span>
<span @click="preview(row)">{{ row.fileName }}</span>

preview回调,预览

// 预览
const previewRef = ref();
const preview = (data) => {
    // 如果是文件夹
    if (data.folderType == 1) {
        // 就调用Navigation组件中的openFolder方法,实现预览
        navigationRef.value.openFolder(data);
        return;
    }
    if (data.status != 2) {
        proxy.Message.warning("文件未完成转码,无法预览");
        return;
    }
    previewRef.value.showPreview(data, 0);
};

navChange回调

// 目录,展示目录
const navChange = (data) => {
    // 从传入的 data 对象中解构出 curFolder 和 categoryId 两个属性,并将它们的值分别赋给新定义的常量 curFolder 和 categoryId
    const { curFolder, categoryId } = data;
    // 将当前文件夹的值更新为传过来的文件夹
    currentFolder.value = curFolder;
    // 展示
    showLoading.value = true;
    // 更新category
    category.value = categoryId;
    loadDataList();
};

无文件上传时,Main.vue展示

<!-- 判断没有文件时 -->
        <div class="no-data" v-else>
          <div class="no-data-inner">
            <!-- 图片 -->
            <Icon iconName="no_data" :width="120" fit="fill"></Icon>
            <!-- 文字提示 -->
            <div class="tips">当前目录为空,上传你的第一个文件吧</div>
            <div class="op-list">
                <!-- 上传 -->
              <el-upload
                :show-file-list="false"
                :with-credentials="true"
                :multiple="true"
                :http-request="addFile"
                :accept="fileAccept"
              >
                <div class="op-item">
                  <Icon iconName="file" :width="60"></Icon>
                  <div>上传文件</div>
                </div>
              </el-upload>
              <!-- 新建目录 -->
              <div class="op-item" v-if="category == 'all'" @click="newFolder">
                <Icon iconName="folder" :width="60"></Icon>
                <div>新建目录</div>
              </div>
            </div>
          </div>
        </div>

四、 上传优化(列表自动刷新)

(1)上传回调 

Main.vue中

// 添加文件回调
const reload = () => {
    showLoading.value = false;
    // 刷新列表
    loadDataList();
};
defineExpose({ reload });

Framework.vue中

<component @addFile="addFile" ref="routerViewRef" :is="Component"></component>
// 上传文件回调
// 上传文件后的刷新列表(调用Uploader子组件中的函数)
const routerViewRef = ref();
const uploadCallbackHandler = () => {
    nextTick(() => {
        // 它首先等待DOM更新完成(通过nextTick)
        // 然后重新加载一个组件(可能是router-view)
        routerViewRef.value.reload();
        // 并最后调用一个函数来获取空间使用情况。
        getUseSpace();
    });
};

五、文件选择(过滤)

组件:分类文件类型
src/js/CategoryInfo.js

export default {
    "all": {
        accept: "*"
    },
    "video": {
        accept: ".mp4,.avi,.rmvb,.mkv,.mov"
    },
    "music": {
        accept: ".mp3,.wav,.wma,.mp2,.flac,.midi,.ra,.ape,.aac,.cda"
    },
    "image": {
        accept: ".jpeg,.jpg,.png,.gif,.bmp,.dds,.psd,.pdt,.webp,.xmp,.svg,.tiff"
    },
    "doc": {
        accept: ".pdf,.doc,.docx,.xls,.xlsx,.txt"
    },
    "others": {
        accept: "*"
    },
}

Main.vue中上传按钮

:accept="fileAccept"

// 实现文件选择
const fileAccept = computed(() => {
    const categoryItem = CategoryInfo[category.value];
    return categoryItem ? categoryItem.accept : "*";
});

六、搜索功能实现

Main.vue中搜索输入框

 <!-- 搜索输入框 -->
                <div class="search-panel">
                    <el-input
                        clearable
                        placeholder="请输入文件名搜索"
                        v-model="fileNameFuzzy"
                        @keyup.enter="search">
                    <template #suffix>
                        <i class="iconfont icon-search" @click="search"></i>
                    </template>
              </el-input>
                </div>
                <!-- 搜索图标 -->
               <div class="iconfont icon-refresh" @click="loadDataList"></div>


回调 

// 搜索功能
const search = () => {
  showLoading.value = true;
  loadDataList();
};

七、文件移动的目录导航

FolderSelect.vue中

<!-- 目录导航 -->
            <div class="navigation-panel">
                <Navigation
                    ref="navigationRef"
                    @navChange="navChange"
                    :watchPath="false"
                ></Navigation>
            </div>
// 绑定导航栏
const navigationRef = ref();
// 调用Navigation子组件中的navChange,使得参数传递给该组件
const navChange = (data) => {
    const { curFolder } = data;
    currentFolder.value = curFolder;
    filePid.value = curFolder.fileId;
    loadAllFolder();
};
// 选择目录(目录导航)
const selectFolder = (data) => {
    navigationRef.value.openFolder(data);
};

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

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

相关文章

gin框架学习笔记(二) ——相关数据与文件的响应

前言 在看是今天的内容之前&#xff0c;我们收先来探究一下&#xff1a;什么是Web应用工作的原理&#xff1f;当然这个问题其实论述起来是很麻烦的&#xff0c;但是我们将它无限的缩小&#xff0c;其实可以简化为一个C/S模型&#xff0c;客户端(Client)负责发送请求&#xff0…

深入理解C#中的IO操作:Path类的详解

文章目录 前言一、Path类的概述二、Path类的主要方法2.1 Path.GetFullPath(string relativePath)2.2 Path.GetDirectoryName(string path)2.3 Path.GetFileName(string path)2.4 Path.GetFileNameWithoutExtension(string path)2.5 Path.GetExtension(string path)2.6 Path.Com…

号外!IP SSL证书申请只需十分钟!

IP SSL证书是一种专为IP地址设计的SSL证书&#xff0c;它使得基于IP地址的网站或服务能够实现HTTPS加密&#xff0c;确保数据在传输过程中的安全性和完整性。以下是关于IP SSL证书的一些技术性要点和申请流程概述&#xff1a; 一、IP SSL证书技术要点 1、适用场景&#xff1a…

spring cloud微服务example 入门第一个例子

新建Maven工程 删除src目录&#xff0c;修改poml.xml <modelVersion>4.0.0</modelVersion><groupId>org.example</groupId> <artifactId>SpringCloud_example</artifactId> <version>1.0-SNAPSHOT</version> <packaging&g…

24年湖南三支一扶报名详细流程(电脑报名)

24年湖南三支一扶报名详细流程&#xff08;电脑报名&#xff09; #湖南三支一扶 #湖南三支一扶考试 #三支一扶报名照片 #三支一扶考试 #三支一扶 #湖南省三支一扶

【AI大模型应用开发】LATS:比ToT和ReAct更强大的大模型思维框架

大家好&#xff0c;我是 同学小张&#xff0c;持续学习C进阶知识和AI大模型应用实战案例&#xff0c;持续分享&#xff0c;欢迎大家点赞关注&#xff0c;共同学习和进步。 我们在大模型中常听说CoT&#xff08;思维链&#xff09;、ToT&#xff08;思维树&#xff09;&#xff…

AI视频教程下载:基于OpenAl、LangChain、 Replicate开发AI应用程序

欢迎来到令人兴奋的 AI 应用世界&#xff01;在这门课程中&#xff0c;你将学习到创建一个能够与用户互动、理解自然语言、处理音频输入&#xff0c;甚至分析图像的真正智能应用所需的技能和技术。 AI 工具和技术 你将获得使用几个知名 AI API 和技术的实际经验。这些行业领先…

【数据结构】栈和队列OJ面试题

20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;由于C语言没有栈的接口&#xff0c;所以我们需要自己造一个“模子”。我们直接copy之前的实现的栈的接口就可以了&#xff08;可以看我之前的博客【数据结构】栈和队列-CSDN博客copy接口&#xff09;&…

VTK图形算法API:vtkSphereSource,球几何数据

大家好&#xff0c;我是先锋&#xff0c;专注于AI领域和编程技术分享&#xff0c;在这里定期分享计算机编程知识&#xff0c;AI应用知识&#xff0c;职场经验&#xff1b; 本系列介绍VTK图像算法API&#xff0c;后续会介绍VTK项目实践应用&#xff0c;关注我&#xff0c;不错过…

开源aodh学习小结

1 介绍 aodh是openstack监控服务&#xff08;Telemetry&#xff09;下的一个模块&#xff0c;telemetry下还有一个模块ceilometer OpenStack Docs: 2024.1 Administrator Guides Get Started on the Open Source Cloud Platform - OpenStack Telemetry - OpenStack 1.1 代码仓…

01-02-3

1、线性表 a.定义&#xff1a; 有n&#xff08;n>0&#xff09;个相同类型的元素组成的有序集合。 数组是线性表的一种。通常用数组实现。 b.线性表的顺序存储 b-1&#xff1a;顺序表结构体的定义 顺序表是一个结构体变量。结构体内部有两个数据&#xff1a;一个用于存…

Nature 综述(IF=88):微生物群落和土壤性质之间的相互作用

随着社会的发展&#xff0c;环境污染和自然资源的消耗日益严重&#xff0c;土壤生态系统的健康状况备受关注。然而&#xff0c;当前研究领域存在一个问题&#xff0c;即在研究土壤微生物群落结构的同时&#xff0c;忽略了微生物对土壤环境的影响。本文旨在探讨微生物如何通过生…

牛客热题:旋转数组的最小数字

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;旋转数组的最小数字题目链接方法…

二叉树的前序、中序、后序遍历

二叉树的前序、中序、后序 1.二叉树的前序遍历 题目&#xff1a; 二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&#xff…

​​​【收录 Hello 算法】第 6 章 哈希表

目录 第 6 章 哈希表 本章内容 第 6 章 哈希表 Abstract 在计算机世界中&#xff0c;哈希表如同一位聪慧的图书管理员。 他知道如何计算索书号&#xff0c;从而可以快速找到目标图书。 本章内容 6.1 哈希表6.2 哈希冲突6.3 哈希算法6.4 小结

UML快速入门篇

目录 1. UML概述 2. 类的表示 2.1. 类的表示 2.2. 抽象类的表示 2.3. 接口的表示 3. 类的属性&#xff0c;方法&#xff0c;访问权限的表示 3.1. 类的属性 3.2. 类的方法 3.3. 类的权限 4. 类的关联 4.1. 单向关联 4.2. 双向关联 4.3. 自关联 4.4. 类的聚合 4.5.…

LeetCode题练习与总结:不同的二叉搜索树Ⅱ--95

一、题目描述 给你一个整数 n &#xff0c;请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,nul…

通过GRE隧道实现OSPF、BGP、IS-IS的套接使用

正文共&#xff1a;999 字 9 图&#xff0c;预估阅读时间&#xff1a;1 分钟 书接上文&#xff08;专线入云场景能否配置动态路由协议&#xff1f;&#xff09;&#xff0c;我们发现通过一定的配置&#xff0c;具体就是组合使用IBGP和静态路由&#xff0c;在使用云专线接入到资…

科技查新中的工法查新点如何确立与提炼?案例讲解!

按《工程建设工法管理办法》( 建 质&#xff3b;2014&#xff3d;103 号) &#xff0c;工法&#xff0c;是指以工程为对象&#xff0c;以工艺为核心&#xff0c;运用系 统工程原理&#xff0c;把先进技术和科学管理结合起来&#xff0c;经过一定工程实践形成的综合配套的施工方…

【go项目01_学习记录11】

操作数据库 1 文章列表2 删除文章 1 文章列表 &#xff08;1&#xff09;先保证文章已经有多篇&#xff0c;可以直接在数据库中添加&#xff0c;或者访问链接: localhost:3000/articles/create&#xff0c;增加几篇文章。 &#xff08;2&#xff09;之前设置好了articles.ind…