|
@@ -1,721 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="cl-upload-space__wrap">
|
|
|
- <slot>
|
|
|
- <el-button v-if="showButton" size="mini" @click="open">点击上传</el-button>
|
|
|
- </slot>
|
|
|
-
|
|
|
- <!-- 弹框 -->
|
|
|
- <cl-dialog :visible.sync="visible" v-bind="props" :op-list="['close']">
|
|
|
- <div class="cl-upload-space">
|
|
|
- <!-- 类目 -->
|
|
|
- <div class="cl-upload-space__category">
|
|
|
- <div class="cl-upload-space__category-search">
|
|
|
- <el-button type="primary" size="mini" @click="editCategory()"
|
|
|
- >添加分类</el-button
|
|
|
- >
|
|
|
-
|
|
|
- <el-input
|
|
|
- v-model="category.keyword"
|
|
|
- placeholder="输入关键字过滤"
|
|
|
- size="mini"
|
|
|
- ></el-input>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="cl-upload-space__category-list">
|
|
|
- <ul>
|
|
|
- <li
|
|
|
- v-for="(item, index) in categoryList"
|
|
|
- :key="index"
|
|
|
- :class="{
|
|
|
- 'is-active': item.id == category.current.id
|
|
|
- }"
|
|
|
- @click="selectCategory(item)"
|
|
|
- @contextmenu.stop.prevent="openCategoryContextMenu($event, item)"
|
|
|
- >
|
|
|
- {{ item.name }}
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 内容 -->
|
|
|
- <div class="cl-upload-space__content">
|
|
|
- <!-- 操作栏 -->
|
|
|
- <div class="cl-upload-space__opbar">
|
|
|
- <el-button
|
|
|
- type="success"
|
|
|
- size="mini"
|
|
|
- :disabled="selection.length === 0"
|
|
|
- @click="confirmFile()"
|
|
|
- >使用选中文件</el-button
|
|
|
- >
|
|
|
-
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- :disabled="selection.length === 0"
|
|
|
- @click="deleteFile()"
|
|
|
- >删除选中文件</el-button
|
|
|
- >
|
|
|
-
|
|
|
- <cl-upload
|
|
|
- style="margin-left: 10px"
|
|
|
- list-type="slot"
|
|
|
- :action="action"
|
|
|
- :accept="accept"
|
|
|
- :limit-size="limitSize"
|
|
|
- :show-file-list="false"
|
|
|
- :headers="headers"
|
|
|
- :data="data"
|
|
|
- :disabled="disabled"
|
|
|
- :rename="rename"
|
|
|
- :on-success="onSuccess"
|
|
|
- :on-progress="onProgress"
|
|
|
- :before-upload="beforeUpload"
|
|
|
- >
|
|
|
- <el-button size="mini" type="primary">点击上传</el-button>
|
|
|
- </cl-upload>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 文件区域 -->
|
|
|
- <div
|
|
|
- class="cl-upload-space__file"
|
|
|
- v-loading="file.loading"
|
|
|
- element-loading-text="拼命加载中"
|
|
|
- >
|
|
|
- <!-- 文件列表 -->
|
|
|
- <el-row v-if="file.list.length > 0">
|
|
|
- <el-col :span="6" v-for="item in file.list" :key="item.id">
|
|
|
- <file-item
|
|
|
- :value="item"
|
|
|
- :element-loading-text="item.progress"
|
|
|
- v-loading="item.loading"
|
|
|
- ></file-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <!-- 空态 -->
|
|
|
- <div class="cl-upload-space__file-empty" v-else>
|
|
|
- <cl-upload
|
|
|
- drag
|
|
|
- :action="action"
|
|
|
- :accept="accept"
|
|
|
- :limit-size="limitSize"
|
|
|
- :headers="headers"
|
|
|
- :data="data"
|
|
|
- :disabled="disabled"
|
|
|
- :rename="rename"
|
|
|
- :on-success="onSuccess"
|
|
|
- :on-progress="onProgress"
|
|
|
- :before-upload="beforeUpload"
|
|
|
- >
|
|
|
- <i class="el-icon-upload"></i>
|
|
|
- <div class="el-upload__text">
|
|
|
- 将文件拖到此处,或<em>点击上传</em>
|
|
|
- </div>
|
|
|
- </cl-upload>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 分页 -->
|
|
|
- <el-pagination
|
|
|
- background
|
|
|
- :page-size="file.pagination.size"
|
|
|
- :current-page="file.pagination.page"
|
|
|
- :total="file.pagination.total"
|
|
|
- @current-change="onCurrentChange"
|
|
|
- ></el-pagination>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </cl-dialog>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import { mapGetters } from "vuex";
|
|
|
-import { last, isEmpty } from "cl-admin/utils";
|
|
|
-
|
|
|
-export default {
|
|
|
- name: "cl-upload-space",
|
|
|
-
|
|
|
- componentName: "UploadSpace",
|
|
|
-
|
|
|
- props: {
|
|
|
- // 上传的地址
|
|
|
- action: String,
|
|
|
- // 选择图片的长度
|
|
|
- limit: {
|
|
|
- type: Number,
|
|
|
- default: 8
|
|
|
- },
|
|
|
- // 最大允许上传文件大小(MB)
|
|
|
- limitSize: {
|
|
|
- type: Number,
|
|
|
- default: 10
|
|
|
- },
|
|
|
- // 是否禁用
|
|
|
- disabled: Boolean,
|
|
|
- // 是否以 uuid 重命名
|
|
|
- rename: Boolean,
|
|
|
- // 设置上传的请求头部
|
|
|
- headers: Object,
|
|
|
- // 上传时附带的额外参数
|
|
|
- data: Object,
|
|
|
- // 上传的文件类型
|
|
|
- accept: String,
|
|
|
- // 是否返回详细数据
|
|
|
- detailData: Boolean,
|
|
|
- // 是否显示按钮
|
|
|
- showButton: {
|
|
|
- type: Boolean,
|
|
|
- default: true
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- components: {
|
|
|
- fileItem: {
|
|
|
- props: {
|
|
|
- value: Object
|
|
|
- },
|
|
|
-
|
|
|
- computed: {
|
|
|
- parent() {
|
|
|
- let parent = this;
|
|
|
-
|
|
|
- while (parent.$options.componentName != "UploadSpace") {
|
|
|
- parent = parent.$parent;
|
|
|
- }
|
|
|
-
|
|
|
- return parent;
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- methods: {
|
|
|
- onSelect() {
|
|
|
- this.parent.selectFile(this.value);
|
|
|
- },
|
|
|
-
|
|
|
- onContextMenu(e) {
|
|
|
- this.parent.openFileContextMenu(e, this.value);
|
|
|
- e.stopPropagation();
|
|
|
- e.preventDefault();
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- render() {
|
|
|
- if (!this.value) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- let itemEl = null;
|
|
|
-
|
|
|
- const { url, type, selected, id } = this.value;
|
|
|
- const fileType = (type || "").split("/")[0];
|
|
|
-
|
|
|
- switch (fileType) {
|
|
|
- case "image":
|
|
|
- itemEl = <el-image fit="cover" src={url} lazy></el-image>;
|
|
|
- break;
|
|
|
-
|
|
|
- case "video":
|
|
|
- itemEl = (
|
|
|
- <video
|
|
|
- controls
|
|
|
- src={url}
|
|
|
- style={{
|
|
|
- "max-height": "100%",
|
|
|
- "max-width": "100%"
|
|
|
- }}></video>
|
|
|
- );
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- itemEl = <span>{url}</span>;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <div
|
|
|
- class={["cl-upload-space__file-item", `is-${fileType}`]}
|
|
|
- on-click={this.onSelect}
|
|
|
- on-contextmenu={this.onContextMenu}>
|
|
|
- {itemEl}
|
|
|
-
|
|
|
- <div class="cl-upload-space__file-size"></div>
|
|
|
-
|
|
|
- {selected && (
|
|
|
- <div class="cl-upload-space__file-mask">
|
|
|
- <i class="el-icon-success"></i>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- data() {
|
|
|
- return {
|
|
|
- visible: false,
|
|
|
- props: {
|
|
|
- title: "文件空间",
|
|
|
- props: {
|
|
|
- "close-on-click-modal": false,
|
|
|
- "append-to-body": true,
|
|
|
- width: "1000px"
|
|
|
- }
|
|
|
- },
|
|
|
- category: {
|
|
|
- list: [],
|
|
|
- current: {},
|
|
|
- keyword: ""
|
|
|
- },
|
|
|
- file: {
|
|
|
- list: [],
|
|
|
- pagination: {
|
|
|
- page: 1,
|
|
|
- size: 12,
|
|
|
- total: 0
|
|
|
- },
|
|
|
- loading: false
|
|
|
- }
|
|
|
- };
|
|
|
- },
|
|
|
-
|
|
|
- computed: {
|
|
|
- ...mapGetters(["token"]),
|
|
|
-
|
|
|
- categoryList() {
|
|
|
- return this.category.list.filter(e => e.name.includes(this.category.keyword));
|
|
|
- },
|
|
|
-
|
|
|
- selection() {
|
|
|
- return this.file.list.filter(e => e.selected);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- filters: {
|
|
|
- file_name(url) {
|
|
|
- return last(url.split("."));
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- created() {
|
|
|
- this.refreshCategory().then(() => {
|
|
|
- this.category.current = this.category.list[0];
|
|
|
- this.refreshFile();
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- methods: {
|
|
|
- open(key) {
|
|
|
- this.visible = true;
|
|
|
- },
|
|
|
-
|
|
|
- close() {
|
|
|
- this.visible = false;
|
|
|
-
|
|
|
- this.$nextTick(() => {
|
|
|
- this.file.list.map(e => {
|
|
|
- this.$set(e, "selected", false);
|
|
|
- });
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 上传成功
|
|
|
- onSuccess(res, file) {
|
|
|
- let item = this.file.list.find(e => file.uid == e.uid);
|
|
|
-
|
|
|
- if (item) {
|
|
|
- item.url = res.data;
|
|
|
-
|
|
|
- this.$service.space.info
|
|
|
- .add({
|
|
|
- url: res.data,
|
|
|
- type: item.type,
|
|
|
- classifyId: item.classifyId
|
|
|
- })
|
|
|
- .then(res => {
|
|
|
- item.loading = false;
|
|
|
- item.id = res.id;
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- this.$message.error(err);
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 上传前,添加文件
|
|
|
- beforeUpload({ tempFilePath, type, uid }) {
|
|
|
- this.file.list.unshift({
|
|
|
- url: tempFilePath,
|
|
|
- type,
|
|
|
- uid,
|
|
|
- classifyId: this.category.current.id,
|
|
|
- loading: true,
|
|
|
- progress: "0%"
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 上传进度
|
|
|
- onProgress({ percent }, file) {
|
|
|
- let item = this.file.list.find(({ uid }) => uid == file.uid);
|
|
|
-
|
|
|
- if (item) {
|
|
|
- item.progress = percent + "%";
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 刷新资源文件
|
|
|
- refreshFile(params) {
|
|
|
- this.file.loading = true;
|
|
|
-
|
|
|
- this.$service.space.info
|
|
|
- .page({
|
|
|
- ...this.file.pagination,
|
|
|
- ...params,
|
|
|
- classifyId: this.category.current.id,
|
|
|
- type: this.accept
|
|
|
- })
|
|
|
- .then(res => {
|
|
|
- this.file.pagination = res.pagination;
|
|
|
- this.file.list = res.list;
|
|
|
- })
|
|
|
- .done(() => {
|
|
|
- this.file.loading = false;
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 刷新分类
|
|
|
- refreshCategory() {
|
|
|
- return this.$service.space.type.list().then(res => {
|
|
|
- res.unshift({
|
|
|
- name: "全部文件",
|
|
|
- id: null
|
|
|
- });
|
|
|
- this.category.list = res;
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 编辑分类
|
|
|
- editCategory(item = {}) {
|
|
|
- this.$crud.openForm({
|
|
|
- title: "添加分类",
|
|
|
- width: "400px",
|
|
|
- items: [
|
|
|
- {
|
|
|
- label: "分类名称",
|
|
|
- prop: "name",
|
|
|
- value: item.name,
|
|
|
- component: {
|
|
|
- name: "el-input",
|
|
|
- attrs: {
|
|
|
- placeholder: "请填写分类名称"
|
|
|
- }
|
|
|
- },
|
|
|
- rules: {
|
|
|
- required: true,
|
|
|
- message: "分类名称不能为空"
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- on: {
|
|
|
- submit: (data, { done, close }) => {
|
|
|
- let next = null;
|
|
|
-
|
|
|
- if (!item.id) {
|
|
|
- next = this.$service.space.type.add(data);
|
|
|
- } else {
|
|
|
- next = this.$service.space.type.update({
|
|
|
- ...data,
|
|
|
- id: item.id
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- next.then(() => {
|
|
|
- this.refreshCategory();
|
|
|
- close();
|
|
|
- }).catch(err => {
|
|
|
- this.$message.error(err);
|
|
|
- done();
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 选择类目
|
|
|
- selectCategory(item) {
|
|
|
- this.category.current = item;
|
|
|
- this.file.pagination = {
|
|
|
- page: 1,
|
|
|
- size: 12,
|
|
|
- total: 0
|
|
|
- };
|
|
|
- this.refreshFile({
|
|
|
- classifyId: item.id
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 打开类目列表右键菜单
|
|
|
- openCategoryContextMenu(e, { id, name }) {
|
|
|
- if (!id) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- this.$crud.openContextMenu(e, {
|
|
|
- list: [
|
|
|
- {
|
|
|
- label: "编辑",
|
|
|
- "suffix-icon": "el-icon-edit",
|
|
|
- callback: (_, done) => {
|
|
|
- done();
|
|
|
- this.editCategory({ id, name });
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- label: "删除",
|
|
|
- "suffix-icon": "el-icon-delete",
|
|
|
- callback: (_, done) => {
|
|
|
- done();
|
|
|
-
|
|
|
- this.$confirm(`此操作将删除【${name}】下的文件, 是否继续?`, "提示", {
|
|
|
- type: "warning"
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- this.$service.space.type
|
|
|
- .delete({
|
|
|
- ids: id
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- this.$message.success("删除成功");
|
|
|
- this.refreshCategory();
|
|
|
-
|
|
|
- // 删除当前类目时,重置选择
|
|
|
- if (id == this.category.current.id) {
|
|
|
- this.category.current = this.category.list[0];
|
|
|
- this.refreshFile();
|
|
|
- }
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- console.error(err);
|
|
|
- this.$message.error(err);
|
|
|
- });
|
|
|
- })
|
|
|
- .catch(() => {});
|
|
|
- }
|
|
|
- }
|
|
|
- ]
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 打开文件列表右键菜单
|
|
|
- openFileContextMenu(e, data) {
|
|
|
- this.$crud.openContextMenu(e, {
|
|
|
- list: [
|
|
|
- {
|
|
|
- label: data.selected ? "取消选中" : "选中",
|
|
|
- "suffix-icon": data.selected ? "el-icon-close" : "el-icon-check",
|
|
|
- callback: (_, done) => {
|
|
|
- this.selectFile(data);
|
|
|
- done();
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- label: "删除",
|
|
|
- "suffix-icon": "el-icon-delete",
|
|
|
- callback: (_, done) => {
|
|
|
- this.deleteFile(data);
|
|
|
- done();
|
|
|
- }
|
|
|
- }
|
|
|
- ]
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // 确认选中文件
|
|
|
- confirmFile() {
|
|
|
- const selection = this.selection.filter((e, i) => i < this.limit);
|
|
|
- const urls = selection.map(e => e.url).join(",");
|
|
|
-
|
|
|
- this.$emit("input", urls);
|
|
|
- this.$emit("confirm", this.detailData ? selection : urls);
|
|
|
-
|
|
|
- this.close();
|
|
|
- },
|
|
|
-
|
|
|
- // 选择文件
|
|
|
- selectFile(item) {
|
|
|
- this.$set(item, "selected", !item.selected);
|
|
|
- },
|
|
|
-
|
|
|
- // 删除选中文件
|
|
|
- deleteFile(...selection) {
|
|
|
- if (isEmpty(selection)) {
|
|
|
- selection = this.selection;
|
|
|
- }
|
|
|
-
|
|
|
- this.$confirm("此操作将删除文件, 是否继续?", "提示", {
|
|
|
- type: "warning"
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- this.$message.success("删除成功");
|
|
|
-
|
|
|
- this.file.list = this.file.list.filter(
|
|
|
- e => !selection.map(e => e.id).includes(e.id)
|
|
|
- );
|
|
|
-
|
|
|
- this.$service.space.info
|
|
|
- .delete({
|
|
|
- ids: selection.map(e => e.id).join(",")
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- this.$message.error(err);
|
|
|
- });
|
|
|
- })
|
|
|
- .catch(() => {});
|
|
|
- },
|
|
|
-
|
|
|
- // 选择页
|
|
|
- onCurrentChange(i) {
|
|
|
- this.refreshFile({
|
|
|
- page: i
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.cl-upload-space {
|
|
|
- display: flex;
|
|
|
- min-height: 520px;
|
|
|
-
|
|
|
- &__category {
|
|
|
- width: 250px;
|
|
|
- margin-right: 20px;
|
|
|
-
|
|
|
- &-search {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 5px;
|
|
|
-
|
|
|
- .el-button {
|
|
|
- margin-right: 10px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-list {
|
|
|
- overflow: hidden auto;
|
|
|
-
|
|
|
- ul {
|
|
|
- li {
|
|
|
- list-style: none;
|
|
|
- font-size: 14px;
|
|
|
- height: 40px;
|
|
|
- line-height: 40px;
|
|
|
- border-bottom: 1px dashed #eee;
|
|
|
- padding: 0 5px;
|
|
|
- cursor: pointer;
|
|
|
-
|
|
|
- &.is-active {
|
|
|
- color: #409eff;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &__content {
|
|
|
- flex: 1;
|
|
|
- }
|
|
|
-
|
|
|
- &__opbar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- &__file {
|
|
|
- height: calc(100% - 80px);
|
|
|
- overflow: hidden auto;
|
|
|
- margin-bottom: 10px;
|
|
|
-
|
|
|
- /deep/.cl-upload-space__file-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- height: 160px;
|
|
|
- width: 160px;
|
|
|
- cursor: pointer;
|
|
|
- position: relative;
|
|
|
- border-radius: 3px;
|
|
|
- box-sizing: border-box;
|
|
|
- border: 1px solid #eee;
|
|
|
- margin: 5px 0;
|
|
|
-
|
|
|
- &.is-image {
|
|
|
- overflow: hidden;
|
|
|
-
|
|
|
- img {
|
|
|
- height: 100%;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.is-video {
|
|
|
- video {
|
|
|
- max-height: 100%;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .cl-upload-space__file-size {
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- background-color: rgba(0, 0, 0, 0.5);
|
|
|
- }
|
|
|
-
|
|
|
- .cl-upload-space__file-mask {
|
|
|
- position: absolute;
|
|
|
- left: 0;
|
|
|
- top: 0;
|
|
|
- height: 100%;
|
|
|
- width: 100%;
|
|
|
- background-color: rgba(0, 0, 0, 0.5);
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- i {
|
|
|
- font-size: 30px;
|
|
|
- color: #67c23a;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-empty {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-top: 100px;
|
|
|
-
|
|
|
- & > div {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- border-radius: 6px;
|
|
|
- cursor: pointer;
|
|
|
- height: 180px;
|
|
|
- width: 360px;
|
|
|
-
|
|
|
- i {
|
|
|
- font-size: 67px;
|
|
|
- color: #c0c4cc;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|