Vue3实战uu云盘(五):文件分享功能

一、文件分享

  • 用户可以将自己的文件(单个文件或单个文件夹的方式)以链接 + 提取码的形式分享出去,其它用户(包括分享该文件的用户)都需要先输入提取码,才能够查看用户分享的文件
  • 获取分享文件的过程:用户输入用户分享的链接,跳转到文件分享的页面,当前页面会立即发请求给后台,求证当前会话是否该分享输入正确过提取码,如果输入过,则正常获取该分享的文件列表信息。如果没有输入过,那么,让用户跳转到输入提取码的页面,然后,发请求给后台,验证提取码是否正确,如果正确,则跳转到文件分享页面。
  • 用户来到文件分享页面,可以预览用户分享的文件、保存用户分享的文件(可单个保存、多个保存)
  • 当前用户所分享的文件在查看文件分享页面时,可以取消分享(整个分享全部取消分享)

src/views/main/ShareFile.vue

  • Object.assign({},data) 完成赋值
  • 复制 分享链接及提取码 (使用vue-clipboard3实现)
  • 可以通过window.location.origin获取当前的域,可参考:浏览器中location详解
<template>
  <div>
    <Dialog
      :show="dialogConfig.show"
      :title="dialogConfig.title"
      :buttons="dialogConfig.buttons"
      width="600px"
      :showCancel="showCancel"
      @close="dialogConfig.show = false"
    >
      <el-form
        :model="formData"
        :rules="rules"
        ref="formDataRef"
        label-width="100px"
        @submit.prevent
      >
        <!-- 文件名 -->
        <el-form-item label="文件"> {{ formData.fileName }} </el-form-item>

        <!-- 选择有效期和提取码 -->
        <template v-if="showType == 0">
          <!-- 有效期 -->
          <el-form-item label="有效期" prop="validType">
            <el-radio-group v-model="formData.validType">
              <el-radio :label="0">1天</el-radio>
              <el-radio :label="1">7天</el-radio>
              <el-radio :label="2">30天</el-radio>
              <el-radio :label="3">永久有效</el-radio>
            </el-radio-group>
          </el-form-item>

          <!-- 提取码-->
          <el-form-item label="提取码" prop="codeType">
            <el-radio-group v-model="formData.codeType">
              <el-radio :label="0">自定义</el-radio>
              <el-radio :label="1">系统生成</el-radio>
            </el-radio-group>
          </el-form-item>

          <!-- 自定义提取码:-->
          <el-form-item prop="code" v-if="formData.codeType == 0">
            <el-input
              clearable
              placeholder="请输入5位提取码"
              v-model.trim="formData.code"
              maxLength="5"
              :style="{ width: '130px' }"
            ></el-input>
          </el-form-item>
        </template>

        <!-- 生成提取码之后,展示分享链接和提取码 -->
        <template v-else>
          <el-form-item label="分享链接">
            {{ shareUrl }}{{ resultInfo.shareId }}
          </el-form-item>
          <el-form-item label="提取码">
            {{ resultInfo.code }}
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="copy">复制链接及提取码</el-button>
          </el-form-item>
        </template>
      </el-form>
    </Dialog>
  </div>
</template>

<script setup>
// 引入实现复制的文件
import useClipboard from "vue-clipboard3";
const { toClipboard } = useClipboard();

import { ref, getCurrentInstance, nextTick } from "vue";

const { proxy } = getCurrentInstance();

// 文档的当前路径
const shareUrl = ref(document.location.origin + "/share/");

const api = {
  shareFile: "/share/shareFile",
};

// 辨别是生成分享链接和提取码之前 还是 生成分享之后,生成前为0,生成后为1
// 是否展示分享表单   0:分享表单   1:分享结果
const showType = ref(0);

const formData = ref({});
const formDataRef = ref();

// 表单校验规则
const rules = {
  // 必填
  validType: [{ required: true, message: "请选择有效期" }],
  codeType: [{ required: true, message: "请选择提取码类型" }],
  code: [
    { required: true, message: "请输入提取码" },
    // Verify.shareCode,之前在Verfiy.js定义过
    { validator: proxy.Verify.shareCode, message: "提取码只能是数字字母" },
    { min: 5, message: "提取码最少5位" },
  ],
};

// 取消按钮
const showCancel = ref(true);

// 定义弹出框的属性
const dialogConfig = ref({
  show: false,
  title: "分享",
  buttons: [
    {
      type: "primary",
      text: "确定",
      click: (e) => {
        share();
      },
    },
  ],
});

// 结果数据
const resultInfo = ref({});

const share = async () => {
  if (Object.keys(resultInfo.value).length > 0) {
    dialogConfig.value.show = false;
    return;
  }
  formDataRef.value.validate(async (valid) => {
    if (!valid) {
      return;
    }
    let params = {};
    Object.assign(params, formData.value);
    let result = await proxy.Request({
      url: api.shareFile,
      params: params,
    });
    if (!result) {
      return;
    }
    showType.value = 1;
    resultInfo.value = result.data;
    dialogConfig.value.buttons[0].text = "关闭";
    showCancel.value = false;
  });
};

// 向父组件 Main 暴露该函数,使得父组件能够调用该函数,并向子组件传递参数
const show = (data) => {
  // 触发时,下面的五个值要初始化

  showCancel.value = true;
  dialogConfig.value.show = true;
  dialogConfig.value.buttons[0].text = "确认";
  showType.value = 0;
  resultInfo.value = {};

  nextTick(() => {
    // 初始化
    formDataRef.value.resetFields();
    // 获取数据
    formData.value = Object.assign({}, data);
  });
};
defineExpose({ show });

// 复制
const copy = async () => {
  await toClipboard(
    `链接: ${shareUrl.value}${resultInfo.value.shareId} 提取码: ${resultInfo.value.code}`
  );
  proxy.Message.success("复制成功");
};
</script>

<style lang="scss" scoped>
</style>

Main.vue

<!-- 分享 -->
<ShareFile ref="shareRef"></ShareFile>


import ShareFile from "./ShareFile.vue";

// 分享文件
// 利用ShareFile组件暴露出的show函数,实现将Main组件中的函数传递给ShareFile组件
const shareRef = ref();
const share = (row) => {
  shareRef.value.show(row);
};

二、文件已分享列表

 src/views/share/Share.vue

  • 使用@import引入css,如:@import "@/assets/file.list.scss";
  • vue-clipboard3实现文本内容复制
  • 实现批量分享,单个分享,取消分享
<template>
  <div>
    <!-- 取消分享按钮 -->
    <div class="top">
      <el-button
        type="primary"
        :disabled="selectIdList.length == 0"
        @click="cancelShareBatch"
      >
        <span class="iconfont icon-cancel"></span>&nbsp取消分享
      </el-button>
    </div>

    <!-- 文件已分享列表 -->
    <div class="file-list">
      <Table
        :columns="columns"
        :showPagination="true"
        :dataSource="tableData"
        :fetch="loadDataList"
        :options="tableOptions"
        @rowSelected="rowSelected"
      >
        <!-- 文件名 -->
        <template #fileName="{ index, row }">
          <!-- showOp(row) 当鼠标放在当前行时,分享下载等图标出现 -->
          <!-- cancelShowOp(row) 当鼠标离开当前行时,分享下载等图标消失 -->
          <div
            class="file-item"
            @mouseenter="showOp(row)"
            @mouseleave="cancelShowOp(row)"
          >
            <!-- 显示文件图标:不同类型 -->
            <template v-if="
                (row.fileType == 3 || row.fileType == 1) && row.status !== 0
              "
            >
              <!-- 如果文件类型是图片或者视频,且已经成功转码,则执行 Icon中的cover -->
              <Icon :cover="row.fileCover"></Icon>
            </template>
            <template v-else>
              <!-- 如果文件夹类型是文件,则文件类型是该文件类型 -->
              <Icon v-if="row.folderType == 0" :fileType="row.fileType"></Icon>
              <!-- 如果文件夹类型是目录,则文件类型就是目录0 -->
              <Icon v-if="row.folderType == 1" :fileType="0"></Icon>
            </template>

            <!-- 显示文件名称 -->
            <span
              class="file-name"
              v-if="!row.showRename"
              :title="row.fileName"
            >
              <span>{{ row.fileName }}</span>
            </span>

            <!-- 当鼠标放在当前行时显示 -->
            <span class="op">
              <template v-if="row.showOp && row.fileId">
                <span class="iconfont icon-link" @click="copy(row)">
                  复制链接
                </span>

                <span class="iconfont icon-cancel" @click="cancelShare(row)">
                  取消分享
                </span>
              </template>
            </span>
          </div>
        </template>
        
        <template #expireTime="{ index, row }">
          {{ row.validType == 3 ? "永久" : row.expireTime }}
        </template>
      </Table>
    </div>
  </div>
</template>

<script setup>
// 引入实现复制的文件
import useClipboard from "vue-clipboard3";
const { toClipboard } = useClipboard();
import { ref, reactive, getCurrentInstance, watch } from "vue";
const { proxy } = getCurrentInstance();

const api = {
  loadDataList: "/share/loadShareList",
  cancelShare: "/share/cancelShare",
};

// 列表头信息
const columns = [
  {
    label: "文件名",
    prop: "fileName",
    scopedSlots: "fileName",
  },
  {
    label: "分享时间",
    prop: "shareTime",
    width: 200,
  },
  {
    label: "失效时间",
    prop: "expireTime",
    scopedSlots: "expireTime",
    width: 200,
  },
  {
    label: "浏览次数",
    prop: "showCount",
    width: 200,
  },
];

// 数据源
const tableData = ref({});
// 表格选项
const tableOptions = {
  extHeight: 20,
  selectType: "checkbox",
};

// 获得数据;
const loadDataList = async () => {
  let params = {
    // 页码
    pageNo: tableData.value.pageNo,
    // 分页大小
    pageSize: tableData.value.pageSize,
  };
  if (params.category !== "all") {
    delete params.filePid;
  }
  let result = await proxy.Request({
    url: api.loadDataList,
    params,
  });
  if (!result) {
    return;
  }
  tableData.value = result.data;
};

// 当鼠标放在当前行时,分享下载等图标出现
// 展示操作
const showOp = (row) => {
  // 关闭所有的显示
  tableData.value.list.forEach((element) => {
    element.showOp = false;
  });
  // 只开启当前显示
  row.showOp = true;
};

// 取消展示
const cancelShowOp = (row) => {
  row.showOp = false;
};

// 文档的当前路径
const shareUrl = ref(document.location.origin + "/share/");
// 复制
const copy = async (data) => {
  await toClipboard(
    `链接: ${shareUrl.value}${data.shareId} 提取码: ${data.code}`
  );
  proxy.Message.success("复制成功");
};

// 行选中
// 多选 批量选中
const selectIdList = ref([]);
const rowSelected = (rows) => {
  selectIdList.value = [];
  rows.forEach((item) => {
    selectIdList.value.push(item.shareId);
  });
};

const cancelShareIdList = ref([]);
// 批量取消分享
const cancelShareBatch = () => {
  if (selectIdList.value.length == 0) {
    return;
  }

  cancelShareIdList.value = selectIdList.value;
  cancelShareDone();
};

// 单个取消分享
const cancelShare = (row) => {
  cancelShareIdList.value = [row.shareId];
  cancelShareDone();
};

// 取消分享http请求
const cancelShareDone = async () => {
  proxy.Confirm(`你确定要取消分享吗?`, async () => {
    let result = await proxy.Request({
      url: api.cancelShare,
      params: {
        shareIds: cancelShareIdList.value.join(","),
      },
    });
    if (!result) {
      return;
    }
    proxy.Message.success("取消分享成功");
    loadDataList();
  });
};
</script>

<style lang="scss" scoped>
@import "@/assets/file.list.scss";
.file-list {
  margin-top: 10px;
  .file-item {
    .file-name {
      span {
        &:hover {
          color: #494944;
        }
      }
    }
    .op {
      width: 170px;
    }
  }
}
</style>

三、外部分享界面

1.添加路由

src/router/index.js

 在framework之外添加:      
        {
            path: '/shareCheck/:shareId',
            name: '分享校验',
            component: () =>
                import ("@/views/webshare/ShareCheck.vue")
        },
        {
            path: '/share/:shareId',
            name: '分享',
            component: () =>
                import ("@/views/webshare/Share.vue")
        },

2.用户输入链接,进入验证界面

其它用户拿到链接之后,将分享链接输入到地址栏,但是,用户第一次输入的话,肯定没有验证过(会话中,没有此分享记录),因此,要跳转到分享验证页面,验证通过之后,该分享记录会存入此会话,当用户再一次进行此分享页面,就会从会话中检测到有此分享记录,此时就不需要再次验证了。

src/views/webshare/ShareCheck.vue

<template>
  <div class="share">
    <div class="body-content">
      <!-- logo+标题 -->
      <div class="logo">
        <span class="iconfont icon-pan"></span>
        <span class="name">uu云盘</span>
      </div>

      <div class="code-panel">
        <!-- 个人信息,头像+名字 -->
        <div class="file-info">
          <!-- 头像 -->
          <div class="avatar">
            <Avatar :userId="shareInfo.userId" :avatar="shareInfo.avatar" :width="50"></Avatar>
          </div>
          <!-- 分享信息 -->
          <div class="share-info">
            <div class="user-info">
              <!-- 名字 -->
              <span class="nick-name">{{ shareInfo.nickName }} </span>
              <span class="share-time">分享于 {{ shareInfo.shareTime }}</span>
            </div>
            <div class="file-name">分享文件:{{ shareInfo.fileName }}</div>
          </div>
        </div>

        <!-- 提取码+按钮 -->
        <div class="code-body">
          <div class="tips">请输入提取码:</div>
          <div class="input-area">
            <el-form :model="formData" :rules="rules" ref="formDataRef" :maxLength="5" @submit.prevent>
              <el-form-item prop="code">
                <el-input class="input" v-model="formData.code" @keyup.enter="checkShare"></el-input>
                <el-button type="primary" @click="checkShare">提取文件</el-button>
              </el-form-item>
            </el-form>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, nextTick } from "vue";
import { useRouter, useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();

const api = {
  getShareInfo: "/showShare/getShareInfo",
  checkShareCode: "/showShare/checkShareCode",
};

const shareId = route.params.shareId;
const shareInfo = ref({});
// 获取数据
const getShareInfo = async () => {
  let result = await proxy.Request({
    url: api.getShareInfo,
    params: {
      shareId,
    },
  });
  if (!result) {
    return;
  }
  shareInfo.value = result.data;
};
getShareInfo();

const formData = ref({});
const formDataRef = ref();
// 校验规则
const rules = {
  code: [
    { required: true, message: "请输入提取码" },
    { min: 5, message: "提取码为5位" },
    { max: 5, message: "提取码为5位" },
  ],
};

// 验证成功,推到share页面
const checkShare = async () => {
  formDataRef.value.validate(async (valid) => {
    if (!valid) {
      return;
    }
    let result = await proxy.Request({
      url: api.checkShareCode,
      params: {
        shareId: shareId,
        code: formData.value.code,
      },
    });
    if (!result) {
      return;
    }
    router.push(`/share/${shareId}`);
  });
};
</script>

<style lang="scss" scoped>
.share {
  height: calc(100vh);
  background: url("../../assets/share_bg.png");
  background-repeat: repeat-x;
  background-position: 0 bottom;
  background-color: #eef2f6;
  display: flex;
  justify-content: center;

  .body-content {
    margin-top: calc(100vh / 5);
    width: 500px;

    .logo {
      display: flex;
      align-items: center;
      justify-content: center;

      .icon-pan {
        font-size: 60px;
        color: #409eff;
      }

      .name {
        font-weight: bold;
        margin-left: 5px;
        font-size: 25px;
        color: #409eff;
      }
    }

    .code-panel {
      margin-top: 20px;
      background: #fff;
      border-radius: 5px;
      overflow: hidden;
      box-shadow: 0 0 7px 1px #5757574f;

      .file-info {
        padding: 10px 20px;
        background: #409eff;
        color: #fff;
        display: flex;
        align-items: center;

        .avatar {
          margin-right: 5px;
        }

        .share-info {
          .user-info {
            display: flex;
            align-items: center;

            .nick-name {
              font-size: 15px;
            }

            .share-time {
              margin-left: 20px;
              font-size: 12px;
            }
          }

          .file-name {
            margin-top: 10px;
            font-size: 12px;
          }
        }
      }

      .code-body {
        padding: 30px 20px 60px 20px;

        .tips {
          font-weight: bold;
        }

        .input-area {
          margin-top: 10px;

          .input {
            flex: 1;
            margin-right: 10px;
          }
        }
      }
    }
  }
}
</style>

3.验证成功后,进入分享界面 

  • 进入分享页面,首先仍然要请求接口,判断当前会话是否已经输入当前分享的提取码,如果没有输入,则跳转到验证页面

src/views/webshare/Share.vue

<template>
  <div class="share">

    <!-- 头部 -->
    <div class="header">
      <div class="header-content">
        <div class="logo" @click="jump">
          <span class="iconfont icon-pan"></span>
          <span class="name">uu云盘</span>
        </div>
      </div>
    </div>

    <div class="share-body">
      <!-- 判断 -->
      <template v-if="Object.keys(shareInfo).length == 0">
        <div
          v-loading="Object.keys(shareInfo).length == 0"
          class="loading"
        ></div>
      </template>
      <template v-else>
        <!-- 分享用户信息时间等 -->
        <div class="share-panel">
          <div class="share-user-info">
            <div class="avatar">
              <Avatar
                :userId="shareInfo.userId"
                :avatar="shareInfo.avatar"
                :width="50"
              ></Avatar>
            </div>
            <div class="share-info">
              <div class="user-info">
                <span class="nick-name">{{ shareInfo.nickName }} </span>
                <span class="share-time">分享于 {{ shareInfo.shareTime }}</span>
              </div>
              <div class="file-name">分享文件:{{ shareInfo.fileName }}</div>
            </div>
          </div>

          <div class="share-op-btn">
            <el-button
              type="primary"
              v-if="shareInfo.currentUser"
              @click="cancelShare"
              ><span class="iconfont icon-cancel"></span>取消分享</el-button
            >
            <el-button
              type="primary"
              v-else
              :disabled="selectFileIdList.length == 0"
              @click="save2MyPan"
              ><span class="iconfont icon-import"></span
              >保存到我的网盘</el-button
            >
          </div>
        </div>
        <!-- 导航栏 -->
        <Navigation
          ref="navigationRef"
          @navChange="navChange"
          :shareId="shareId"
        ></Navigation>
        <!-- 分享文件列表 -->
        <div class="file-list">
          <Table
            :columns="columns"
            :showPagination="true"
            :dataSource="tableData"
            :fetch="loadDataList"
            :initFetch="false"
            :options="tableOptions"
            @rowSelected="rowSelected"
          >
            <!-- 文件名 -->
            <template #fileName="{ index, row }">
              <!-- showOp(row) 当鼠标放在当前行时,分享下载等图标出现 -->
              <!-- cancelShowOp(row) 当鼠标离开当前行时,分享下载等图标消失 -->
              <div
                class="file-item"
                @mouseenter="showOp(row)"
                @mouseleave="cancelShowOp(row)"
              >
                <!-- 显示文件图标 -->
                <template
                  v-if="
                    (row.fileType == 3 || row.fileType == 1) && row.status !== 0
                  "
                >
                  <!-- 如果文件类型是图片或者视频,且已经成功转码,则执行 Icon中的cover -->
                  <Icon :cover="row.fileCover"></Icon>
                </template>
                <template v-else>
                  <!-- 如果文件夹类型是文件,则文件类型是该文件类型 -->
                  <Icon
                    v-if="row.folderType == 0"
                    :fileType="row.fileType"
                  ></Icon>
                  <!-- 如果文件夹类型是目录,则文件类型就是目录0 -->
                  <Icon v-if="row.folderType == 1" :fileType="0"></Icon>
                </template>

                <!-- 显示文件名称 -->
                <!-- v-if="!row.showEdit" 如果该行文件没有编辑 -->
                <span class="file-name" :title="row.fileName">
                  <span @click="preview(row)">{{ row.fileName }}</span>
                </span>

                <!-- 当鼠标放在当前行时显示 -->
                <span class="op">
                  <!-- 只有当是文件夹时才可下载 -->
                  <span
                    v-if="row.folderType == 0"
                    class="iconfont icon-download"
                    @click="download(row.fileId)"
                    >下载</span
                  >
                  <template v-if="row.showOp && !shareInfo.currentUser">
                    <span
                      class="iconfont icon-import"
                      @click="save2MyPanSingle(row)"
                      >保存到我的网盘</span
                    >
                  </template>
                </span>
              </div>
            </template>

            <!-- 文件大小 -->
            <template #fileSize="{ index, row }">
              <span v-if="row.fileSize">
                {{ proxy.Utils.size2Str(row.fileSize) }}</span
              >
            </template>
          </Table>
        </div>
      </template>
      <!-- 选择目录 -->
      <FolderSelect
        ref="folderSelectRef"
        @folderSelect="save2MyPanDone"
      ></FolderSelect>

      <!-- 预览 -->
      <Preview ref="previewRef"></Preview>
    </div>
  </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();

const api = {
  getShareLoginInfo: "/showShare/getShareLoginInfo",
  loadFileList: "/showShare/loadFileList",
  createDownloadUrl: "/showShare/createDownloadUrl",
  download: "/api/showShare/download",
  cancelShare: "/share/cancelShare",
  saveShare: "/showShare/saveShare",
};

const shareId = route.params.shareId;
const shareInfo = ref({});

// 获取数据
const getShareInfo = async () => {
  let result = await proxy.Request({
    url: api.getShareLoginInfo,
    params: {
      shareId,
    },
  });
  if (result.data == null) {
    router.push("/shareCheck/" + shareId);
    return;
  }
  shareInfo.value = result.data;
};
getShareInfo();

//列表
const columns = [
  {
    label: "文件名",
    prop: "fileName",
    scopedSlots: "fileName",
  },
  {
    label: "修改时间",
    prop: "lastUpdateTime",
    width: 200,
  },
  {
    label: "大小",
    prop: "fileSize",
    scopedSlots: "fileSize",
    width: 200,
  },
];

const tableData = ref({});
const tableOptions = {
  extHeight: 80,
  selectType: "checkbox",
};

// 获得数据;
const loadDataList = async () => {
  let params = {
    // 页码
    pageNo: tableData.value.pageNo,
    // 分页大小
    pageSize: tableData.value.pageSize,
    shareId: shareId,
    filePid: currentFolder.value.fileId,
  };
  let result = await proxy.Request({
    url: api.loadFileList,
    params,
  });
  if (!result) {
    return;
  }
  tableData.value = result.data;
};

// 当鼠标放在当前行时,分享下载等图标出现
const showOp = (row) => {
  // 关闭所有的显示
  tableData.value.list.forEach((element) => {
    element.showOp = false;
  });
  // 只开启当前显示
  row.showOp = true;
};

const cancelShowOp = (row) => {
  row.showOp = false;
};

// 行选中
// 多选 批量选中
const selectFileIdList = ref([]);
const rowSelected = (rows) => {
  selectFileIdList.value = [];
  rows.forEach((item) => {
    selectFileIdList.value.push(item.fileId);
  });
};

const currentFolder = ref({ fileId: "0" });
// 目录
const navChange = (data) => {
  const { curFolder } = data;
  currentFolder.value = curFolder;
  loadDataList();
};

// 预览
const previewRef = ref();
const preview = (data) => {
  // 如果是目录(文件夹)
  if (data.folderType == 1) {
    navigationRef.value.openFolder(data);
    return;
  }
  data.shareId = shareId;
  previewRef.value.showPreview(data, 2);
};

// 下载文件
const download = async (fileId) => {
  let result = await proxy.Request({
    url: api.createDownloadUrl + "/" + shareId + "/" + fileId,
  });

  if (!result) {
    return;
  }

  window.location.href = api.download + "/" + result.data;
};

// 保存到我的网盘
const folderSelectRef = ref();
const save2MyPanFileIdArray = [];

// 批量保存
const save2MyPan = () => {
  if (selectFileIdList.value.length == 0) {
    return;
  }
  if (!proxy.VueCookies.get("userInfo")) {
    router.push("/login?redirectUrl=" + route.path);
    return;
  }
  save2MyPanFileIdArray.values = selectFileIdList.value;
  folderSelectRef.value.showFolderDialog();
};

// 单个保存
const save2MyPanSingle = (row) => {
  if (!proxy.VueCookies.get("userInfo")) {
    router.push("/login?redirectUrl=" + route.path);
    return;
  }
  save2MyPanFileIdArray.values = [row.fileId];
  folderSelectRef.value.showFolderDialog();
};

// 执行保存操作
const save2MyPanDone = async (folderId) => {
  let result = await proxy.Request({
    url: api.saveShare,
    params: {
      shareId: shareId,
      shareFileIds: save2MyPanFileIdArray.values.join(","),
      myFolderId: folderId,
    },
  });
  if (!result) {
    return;
  }
  loadDataList();
  proxy.Message.success("保存成功");
  folderSelectRef.value.close();
};

const cancelShare = () => {
  proxy.Confirm(`你确定要取消分享吗?`, async () => {
    let result = await proxy.Request({
      url: api.cancelShare,
      params: {
        shareIds: shareId,
      },
    });
    if (!result) {
      return;
    }
    proxy.Message.success("取消分享成功");
    router.push("/");
  });
};

const jump = () => {
  router.push("/");
};
</script>

<style lang="scss" scoped>
@import "@/assets/file.list.scss";
.header {
  width: 100%;
  position: fixed;
  background: #0c95f7;
  height: 50px;
  .header-content {
    width: 70%;
    margin: 0px auto;
    color: #fff;
    line-height: 50px;
    .logo {
      display: flex;
      align-items: center;
      cursor: pointer;
      .icon-pan {
        font-size: 40px;
      }
      .name {
        font-weight: bold;
        margin-left: 5px;
        font-size: 25px;
      }
    }
  }
}
.share-body {
  width: 70%;
  margin: 0px auto;
  padding-top: 50px;
  .loading {
    height: calc(100vh / 2);
    width: 100%;
  }
  .share-panel {
    margin-top: 20px;
    display: flex;
    justify-content: space-around;
    border-bottom: 1px solid #ddd;
    padding-bottom: 10px;
    .share-user-info {
      flex: 1;
      display: flex;
      align-items: center;
      .avatar {
        margin-right: 5px;
      }
      .share-info {
        .user-info {
          display: flex;
          align-items: center;
          .nick-name {
            font-size: 15px;
          }
          .share-time {
            margin-left: 20px;
            font-size: 12px;
          }
        }
        .file-name {
          margin-top: 10px;
          font-size: 12px;
        }
      }
    }
  }
}

.file-list {
  margin-top: 10px;
  .file-item {
    .op {
      width: 170px;
    }
  }
}
</style>

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值