677 lines
25 KiB
PHP
677 lines
25 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="{{ locale() }}">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<base href="{{ $admin_base_url }}">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
<meta name="asset" content="{{ asset('/') }}">
|
||
<script src="{{ asset('vendor/vue/2.7/vue.js') }}"></script>
|
||
<script src="{{ asset('vendor/element-ui/index.js') }}"></script>
|
||
<script src="{{ asset('vendor/cookie/js.cookie.min.js') }}"></script>
|
||
<script src="{{ asset('vendor/jquery/jquery-3.6.0.min.js') }}"></script>
|
||
<script src="{{ asset('vendor/layer/3.5.1/layer.js') }}"></script>
|
||
<script src="{{ asset('vendor/vue/batch_select.js') }}"></script>
|
||
<link href="{{ mix('/build/beike/admin/css/bootstrap.css') }}" rel="stylesheet">
|
||
<link rel="stylesheet" href="{{ asset('vendor/element-ui/index-blue.css') }}">
|
||
<link href="{{ mix('build/beike/admin/css/filemanager.css') }}" rel="stylesheet">
|
||
<script src="{{ mix('build/beike/admin/js/app.js') }}"></script>
|
||
@if (locale() != 'zh_cn')
|
||
<script src="{{ asset('vendor/element-ui/language/' . locale() . '.js') }}"></script>
|
||
@endif
|
||
<title>beike filemanager</title>
|
||
<script>
|
||
@if (locale() != 'zh_cn')
|
||
ELEMENT.locale(ELEMENT.lang['{{ locale() }}'])
|
||
@endif
|
||
const lang = {
|
||
file_manager: '{{ __('admin/file_manager.file_manager') }}',
|
||
}
|
||
|
||
const config = {
|
||
beike_version: '{{ config('beike.version') }}',
|
||
api_url: '{{ config('beike.api_url') }}',
|
||
app_url: '{{ config('app.url') }}',
|
||
}
|
||
</script>
|
||
</head>
|
||
|
||
<body class="page-filemanager">
|
||
<div class="filemanager-wrap" id="filemanager-wrap-app" v-cloak ref="splitPane">
|
||
@if (!is_mobile())
|
||
<div class="filemanager-navbar" :style="'width:' + paneLengthValue">
|
||
<el-tree :props="defaultProps" node-key="path" :data="treeData" :current-node-key="folderCurrent"
|
||
:default-expanded-keys="defaultkeyarr" :expand-on-click-node="false" highlight-current ref="tree"
|
||
@node-click="handleNodeClick" @node-expand="(node) => {updateDefaultExpandedKeys(node, 'expand')}"
|
||
@node-collapse="(node) => {updateDefaultExpandedKeys(node, 'collapse')}" class="tree-wrap">
|
||
<div class="custom-tree-node" slot-scope="{ node, data }">
|
||
<div>@{{ node.label }}</div>
|
||
{{-- v-if="node.isCurrent" --}}
|
||
<div class="right">
|
||
<el-tooltip class="item" effect="dark" content="{{ __('admin/file_manager.create_folder') }}" placement="top">
|
||
<span @click.stop="() => {openInputBox('addFolder', node, data)}"><i
|
||
class="el-icon-circle-plus-outline"></i></span>
|
||
</el-tooltip>
|
||
|
||
<el-tooltip class="item" effect="dark" content="{{ __('admin/file_manager.rename') }}" placement="top">
|
||
<span v-if="node.level != 1" @click.stop="() => {openInputBox('renameFolder', node, data)}"><i
|
||
class="el-icon-edit"></i></span>
|
||
</el-tooltip>
|
||
|
||
<el-tooltip class="item" effect="dark" content="{{ __('common.delete') }}" placement="top">
|
||
<span v-if="node.level != 1" @click.stop="() => {deleteFolder(node, data)}"><i
|
||
class="el-icon-delete"></i></span>
|
||
</el-tooltip>
|
||
|
||
</div>
|
||
</div>
|
||
</el-tree>
|
||
</div>
|
||
<div class="filemanager-divider" @mousedown="handleMouseDown"></div>
|
||
<div class="filemanager-content" v-loading="loading" element-loading-background="rgba(255, 255, 255, 0.5)">
|
||
<div class="content-head">
|
||
<div class="left d-lg-flex">
|
||
<el-button class="me-5 mb-1 mb-lg-0" size="small" icon="el-icon-check" type="primary" @click="fileChecked" :disabled="!!!selectImageIndex.length">{{ __('admin/builder.modules_choose') }}</el-button>
|
||
<el-link :underline="false" :disabled="!!!selectImageIndex.length" icon="el-icon-view"
|
||
@click="viewImages">{{ __('common.view') }}</el-link>
|
||
<el-link :underline="false" :disabled="!!!selectImageIndex.length" @click="deleteFile"
|
||
icon="el-icon-delete">{{ __('common.delete') }}</el-link>
|
||
<el-link :underline="false" :disabled="selectImageIndex.length == 1 ? false : true"
|
||
@click="openInputBox('image')" icon="el-icon-edit">{{ __('admin/file_manager.rename') }}</el-link>
|
||
<el-link :underline="false" :disabled="!!!images.length && !!!selectImageIndex.length"
|
||
@click="selectAll()" icon="el-icon-finished">{{ __('common.select_all') }}</el-link>
|
||
@hook('admin.file_manager.content.head.btns.after')
|
||
</div>
|
||
<div class="right">
|
||
<el-popover
|
||
placement="bottom"
|
||
width="260"
|
||
class="me-2"
|
||
trigger="click">
|
||
<div class="text-center mb-3 fw-bold">{{ __('admin/file_manager.file_sorting') }}</div>
|
||
<div class="mb-3">
|
||
<div class="mb-2">{{ __('admin/file_manager.text_type') }}</div>
|
||
<el-radio-group v-model="filter.sort" size="small">
|
||
<el-radio-button label="created">{{ __('admin/file_manager.text_created') }}</el-radio-button>
|
||
<el-radio-button label="name">{{ __('admin/file_manager.file_name') }}</el-radio-button>
|
||
</el-radio-group>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<div class="mb-2">{{ __('admin/file_manager.to_sort') }}</div>
|
||
<el-radio-group v-model="filter.order" size="small">
|
||
<el-radio-button label="desc">{{ __('admin/file_manager.text_desc') }}</el-radio-button>
|
||
<el-radio-button label="asc">{{ __('admin/file_manager.text_asc') }}</el-radio-button>
|
||
</el-radio-group>
|
||
</div>
|
||
<el-button slot="reference" size="small" plain type="primary" icon="el-icon-s-operation"></el-button>
|
||
</el-popover>
|
||
<el-button size="small" plain type="primary" @click="openUploadFile" icon="el-icon-upload2">{{ __('admin/file_manager.upload_files') }}</el-button>
|
||
</div>
|
||
</div>
|
||
<div v-if="images.length" class="content-center"
|
||
v-batch-select="{ className: '.image-list', selectImageIndex, setSelectStatus: updateSelectStatus }">
|
||
<div :class="['image-list', file.selected ? 'active' : '']" v-for="file, index in images"
|
||
:key="index" @click="checkedImage(index)">
|
||
<div class="img">
|
||
<i class="el-icon-video-play" v-if="file.mime == 'video/mp4'"></i>
|
||
<img v-else :src="file.url">
|
||
</div>
|
||
<div class="text">
|
||
<span :title="file.name">@{{ file.name }}</span>
|
||
<i v-if="file.selected" class="el-icon-check"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<el-empty v-else description="{{ __('admin/file_manager.no_file') }}"></el-empty>
|
||
<div class="content-footer">
|
||
<div class="right"></div>
|
||
<div class="pagination-wrap">
|
||
<el-pagination
|
||
@size-change="pageSizeChange"
|
||
@current-change="pageCurrentChange"
|
||
:current-page="image_page"
|
||
:page-sizes="[20, 40, 60, 80, 100]"
|
||
:page-size="20"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:total="image_total">
|
||
</el-pagination>
|
||
|
||
</div>
|
||
<div class="right">
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@else
|
||
<div class="text-center mt-5 w-100 fs-4">{{ __('admin/file_manager.show_pc') }}</div>
|
||
@endif
|
||
|
||
<el-dialog title="{{ __('admin/file_manager.upload_files') }}" top="12vh" :visible.sync="uploadFileDialog.show" width="500px"
|
||
@close="uploadFileDialogClose" custom-class="upload-wrap">
|
||
<el-upload class="photos-upload" target="photos-upload" id="photos-upload" element-loading-text="{{ __('admin/file_manager.image_uploading') }}..."
|
||
element-loading-background="rgba(0, 0, 0, 0.6)" drag action="" :show-file-list="false"
|
||
accept=".jpg,.jpeg,.png,.JPG,.JPEG,.PNG,.mp4,.MP4,.gif,.webp" :before-upload="beforePhotoUpload"
|
||
:on-success="handlePhotoSuccess" :on-change="handleUploadChange" :http-request="uploadFile"
|
||
:multiple="true">
|
||
<i class="el-icon-upload"></i>
|
||
<div class="el-upload__text">{{ __('admin/file_manager.click_upload') }}</div>
|
||
</el-upload>
|
||
<div class="upload-image">
|
||
<div v-for="image, index in uploadFileDialog.images" :key="index" class="list">
|
||
<div class="info">
|
||
<div class="name">@{{ index + 1 }}. @{{ image.name }}</div>
|
||
<div class="status">
|
||
<span v-if="image.status == 'complete'" class="text-success">{{ __('admin/file_manager.finish') }}</span>
|
||
<span v-else-if="image.status == 'fail'" class="text-danger">{{ __('admin/file_manager.upload_fail') }}</span>
|
||
<span v-else>{{ __('admin/file_manager.uploading') }}</span>
|
||
</div>
|
||
</div>
|
||
<el-progress :percentage="image.progre" :status="image.status == 'fail' ? 'exception' : 'success'" :show-text="false" :stroke-width="4"></el-progress>
|
||
<div v-if="image.fail_text" class="mt-1 text-danger" v-text="image.fail_text"></div>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
<script>
|
||
@if (locale() != 'zh_cn')
|
||
ELEMENT.locale(ELEMENT.lang['{{ locale() }}'])
|
||
@endif
|
||
var callback = null;
|
||
|
||
var app = new Vue({
|
||
el: '#filemanager-wrap-app',
|
||
components: {},
|
||
data: {
|
||
min: 10,
|
||
max: 40,
|
||
paneLengthPercent: 26,
|
||
triggerLength: 10,
|
||
isShift: false,
|
||
mime: @json(request('mime')),
|
||
loading: false,
|
||
isBatchSelect: false,
|
||
selectImageIndex: [],
|
||
filter: {
|
||
sort: 'created',
|
||
order: 'desc'
|
||
},
|
||
|
||
treeData: [{
|
||
name: '{{ __('admin/file_manager.picture_space') }}',
|
||
path: '/',
|
||
children: @json($directories)
|
||
}],
|
||
|
||
defaultProps: {
|
||
children: 'children',
|
||
label: 'name',
|
||
isLeaf: 'leaf'
|
||
},
|
||
selectIdxs: [],
|
||
|
||
uploadFileDialog: {
|
||
show: false,
|
||
total: 0,
|
||
images: []
|
||
},
|
||
|
||
folderCurrent: '/',
|
||
defaultkeyarr: ['/'],
|
||
|
||
triggerLeftOffset: 0,
|
||
|
||
images: [],
|
||
image_total: 0,
|
||
image_page: 1,
|
||
per_page: 20,
|
||
@stack('admin.file_manager.vue.data')
|
||
},
|
||
// 计算属性
|
||
computed: {
|
||
paneLengthValue() {
|
||
return `calc(${this.paneLengthPercent}% - ${this.triggerLength / 2 + 'px'})`
|
||
},
|
||
},
|
||
// 侦听器
|
||
watch: {
|
||
images: {
|
||
handler(val) {
|
||
if (this.isBatchSelect) return;
|
||
// 将选中的图片索引放入 selectImageIndex,未选中则清空
|
||
this.selectImageIndex = val.filter(item => item.selected).map(e => this.images.indexOf(e));
|
||
},
|
||
deep: true
|
||
},
|
||
|
||
selectImageIndex(indexs) {
|
||
this.images.forEach((item, index) => {
|
||
item.selected = indexs.includes(index);
|
||
});
|
||
},
|
||
|
||
filter: {
|
||
handler(val) {
|
||
this.image_page = 1;
|
||
this.loadData()
|
||
},
|
||
deep: true
|
||
}
|
||
},
|
||
// 组件方法
|
||
methods: {
|
||
handleNodeClick(e, node) {
|
||
if (e.path == this.folderCurrent) {
|
||
return;
|
||
}
|
||
|
||
this.folderCurrent = e.path
|
||
this.image_page = 1;
|
||
sessionStorage.setItem('folderCurrent', this.folderCurrent);
|
||
this.loadData(e, node)
|
||
},
|
||
|
||
updateSelectStatus(status) {
|
||
this.isBatchSelect = status
|
||
},
|
||
|
||
pageCurrentChange(e) {
|
||
this.image_page = e
|
||
this.loadData()
|
||
},
|
||
|
||
pageSizeChange(e) {
|
||
this.per_page = e
|
||
this.loadData()
|
||
},
|
||
|
||
uploadFileDialogClose() {
|
||
if (this.uploadFileDialog.images.length) {
|
||
this.loadData()
|
||
}
|
||
|
||
this.uploadFileDialog.images = [];
|
||
},
|
||
|
||
openUploadFile() {
|
||
this.uploadFileDialog.show = true
|
||
},
|
||
|
||
beforePhotoUpload(file) {
|
||
// this.editing.photoLoading = true;
|
||
},
|
||
|
||
handlePhotoSuccess(data) {
|
||
// this.editing.photoLoading = false;
|
||
|
||
// if (data.images) {
|
||
// this.images.push(data.images);
|
||
// }
|
||
},
|
||
|
||
// 文件上传
|
||
uploadFile(file) {
|
||
const that = this;
|
||
let newFile = {};
|
||
|
||
var formData = new FormData();
|
||
formData.append("file", file.file, file.file.name);
|
||
formData.append("path", this.folderCurrent);
|
||
|
||
newFile = {
|
||
// index: this.images.length,
|
||
name: file.file.name,
|
||
progre: 0,
|
||
status: 'padding'
|
||
};
|
||
|
||
this.uploadFileDialog.images.push(newFile);
|
||
|
||
let index = this.uploadFileDialog.images.length - 1;
|
||
|
||
$http.post('file_manager/upload', formData, {hmsg: true}).then((res) => {
|
||
this.uploadFileDialog.images[index].status = 'complete';
|
||
this.uploadFileDialog.images[index].progre = 100;
|
||
}).catch((err) => {
|
||
this.uploadFileDialog.images[index].status = 'fail';
|
||
this.uploadFileDialog.images[index].progre = 80;
|
||
this.uploadFileDialog.images[index].fail_text = err.response.data.message;
|
||
}).finally(() => {
|
||
index += 1
|
||
});
|
||
},
|
||
|
||
handleUploadChange(e) {
|
||
console.log(e);
|
||
// console.log('handleUploadChange');
|
||
},
|
||
|
||
updateDefaultExpandedKeys(node, type) {
|
||
const isExist = this.defaultkeyarr.some(item => item === node.path)
|
||
|
||
if (type == 'expand') {
|
||
if (!isExist) {
|
||
this.defaultkeyarr.push(node.path)
|
||
}
|
||
} else {
|
||
const index = this.defaultkeyarr.findIndex(e => e == node.path);
|
||
if (index > -1) {
|
||
this.defaultkeyarr.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
sessionStorage.setItem('defaultkeyarr', this.defaultkeyarr);
|
||
},
|
||
|
||
loadData(e, node) {
|
||
this.loading = true;
|
||
|
||
$http.get(`file_manager/files?base_folder=${this.folderCurrent}`, {
|
||
page: this.image_page,
|
||
per_page: this.per_page,
|
||
sort: this.filter.sort,
|
||
order: this.filter.order
|
||
}, {
|
||
hload: true
|
||
}).then((res) => {
|
||
this.images = res.images
|
||
this.image_page = res.image_page
|
||
this.image_total = res.image_total
|
||
|
||
if (node) {
|
||
node.expanded = true
|
||
this.updateDefaultExpandedKeys(node.data, 'expand')
|
||
}
|
||
}).finally(() => this.loading = false);
|
||
},
|
||
|
||
// 按下滑动器
|
||
handleMouseDown(e) {
|
||
document.addEventListener('mousemove', this.handleMouseMove)
|
||
document.addEventListener('mouseup', this.handleMouseUp)
|
||
|
||
this.triggerLeftOffset = e.pageX - e.srcElement.getBoundingClientRect().left
|
||
},
|
||
|
||
// 按下滑动器后移动鼠标
|
||
handleMouseMove(e) {
|
||
const clientRect = this.$refs.splitPane.getBoundingClientRect()
|
||
let paneLengthPercent = 0
|
||
|
||
const offset = e.pageX - clientRect.left - this.triggerLeftOffset + this.triggerLength / 2
|
||
paneLengthPercent = (offset / clientRect.width) * 100
|
||
|
||
if (paneLengthPercent < this.min) {
|
||
paneLengthPercent = this.min
|
||
}
|
||
if (paneLengthPercent > this.max) {
|
||
paneLengthPercent = this.max
|
||
}
|
||
this.paneLengthPercent = paneLengthPercent;
|
||
},
|
||
|
||
// 松开滑动器
|
||
handleMouseUp() {
|
||
document.removeEventListener('mousemove', this.handleMouseMove)
|
||
},
|
||
|
||
checkedImage(index) {
|
||
// 获取当前选中的 index
|
||
const selectedIndex = this.images.findIndex(e => e.selected);
|
||
|
||
if (this.isShift) {
|
||
// 获取 selectedIndex 与 index 之间的所有图片
|
||
let selectedImages = this.images.slice(Math.min(selectedIndex, index), Math.max(selectedIndex, index) +
|
||
1);
|
||
selectedImages.map(e => e.selected = true)
|
||
return;
|
||
}
|
||
|
||
if (this.isCtrl) {
|
||
this.images[index].selected = !this.images[index].selected;
|
||
return;
|
||
}
|
||
|
||
if (this.selectImageIndex.length > 1) {
|
||
this.images.map((e, i) => i != index ? e.selected = false : e.selected = true)
|
||
return;
|
||
}
|
||
|
||
this.images.map((e, i) => i != index ? e.selected = false : '')
|
||
this.images[index].selected = !this.images[index].selected
|
||
},
|
||
|
||
// 选取
|
||
fileChecked() {
|
||
let typedFiles = this.images.filter(e => e.selected)
|
||
|
||
if (this.mime) {
|
||
// 判断 typedFiles 数组内 mime 是否有不是 image 开头的
|
||
if (this.mime == 'image' && typedFiles.some(e => !e.mime.startsWith('image'))) {
|
||
layer.msg('{{ __('admin/file_manager.verify_select_image') }}', () => {});
|
||
return;
|
||
}
|
||
|
||
// 判断 typedFiles 数组内 mime 是否有不是 video 开头的
|
||
if (this.mime == 'video' && typedFiles.some(e => !e.mime.startsWith('video'))) {
|
||
layer.msg('{{ __('admin/file_manager.verify_select_video') }}', () => {});
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (callback !== null) {
|
||
callback(typedFiles);
|
||
}
|
||
|
||
// 关闭弹窗
|
||
var index = parent.layer.getFrameIndex(window.name);
|
||
parent.layer.close(index);
|
||
},
|
||
|
||
deleteFile() {
|
||
this.$confirm('{{ __('admin/file_manager.confirm_delete_file') }}', '{{ __('common.text_hint') }}', {
|
||
type: 'warning'
|
||
}).then(() => {
|
||
const selectImageIndex = this.selectImageIndex;
|
||
// 获取images中下标与selectImageIndex相同的图片
|
||
const images = this.images.filter(e => selectImageIndex.includes(this.images.indexOf(e)));
|
||
// images 取 path 组成数组 然后用 | 分割成字符串
|
||
const files = images.map(e => e.name);
|
||
|
||
this.loading = true;
|
||
|
||
$http.delete('file_manager/files', {
|
||
path: this.folderCurrent,
|
||
files: files
|
||
}, {
|
||
hload: true
|
||
}).then((res) => {
|
||
layer.msg(res.message)
|
||
this.loadData()
|
||
})
|
||
}).catch(_ => {});
|
||
},
|
||
|
||
deleteFolder(node, data) {
|
||
if (data.path) {
|
||
this.$confirm('{{ __('admin/file_manager.confirm_delete_folder') }}', '{{ __('common.text_hint') }}', {
|
||
type: 'warning'
|
||
}).then(() => {
|
||
$http.delete(`file_manager/directories`, {
|
||
name: data.path
|
||
}).then((res) => {
|
||
layer.msg(res.message)
|
||
this.$refs.tree.setCurrentKey(node.parent.data.path)
|
||
this.folderCurrent = node.parent.data.path;
|
||
this.$refs.tree.remove(data.path)
|
||
}).finally(() => this.loadData())
|
||
}).catch(_ => {});
|
||
}
|
||
},
|
||
|
||
selectAll() {
|
||
// 获取 this.images 中的 selected 是否全部为 true
|
||
const isAllSelected = this.images.every(e => e.selected);
|
||
this.images.map(e => e.selected = !isAllSelected)
|
||
},
|
||
|
||
downloadImages() {
|
||
// 获取选中的图片
|
||
const selectedImages = this.images.filter(e => e.selected);
|
||
// 创建 a 标签
|
||
selectedImages.forEach(e => {
|
||
const a = document.createElement('a');
|
||
// 设置 a 标签的 href 属性
|
||
a.href = e.origin_url;
|
||
// 设置 a 标签的 download 属性
|
||
a.download = e.name;
|
||
// 触发 a 标签的 click 事件
|
||
a.click();
|
||
});
|
||
},
|
||
|
||
viewImages() {
|
||
const selectedImages = this.images.filter(e => e.selected);
|
||
selectedImages.forEach(e => {
|
||
window.open(e.origin_url);
|
||
});
|
||
},
|
||
|
||
openInputBox(type, node, data) {
|
||
let fileSuffix, fileName = '';
|
||
|
||
if (type == 'image') {
|
||
const image = this.images[this.selectImageIndex].name;
|
||
// 获取文件后缀
|
||
fileSuffix = image.substring(image.lastIndexOf('.') + 1);
|
||
// 获取文件名
|
||
fileName = image.substring(0, image.lastIndexOf('.'));
|
||
}
|
||
|
||
this.$prompt('', type == 'addFolder' ? '{{ __('admin/file_manager.new_folder') }}' : '{{ __('admin/file_manager.rename') }}', {
|
||
confirmButtonText: '{{ __('common.confirm') }}',
|
||
cancelButtonText: '{{ __('common.cancel') }}',
|
||
inputPattern: /^.+$/,
|
||
closeOnClickModal: false,
|
||
inputValue: type == 'image' ? fileName : (type == 'renameFolder' ? data.name : '{{ __('admin/file_manager.new_folder') }}'),
|
||
inputErrorMessage: '{{ __('admin/file_manager.can_empty') }}'
|
||
}).then(({
|
||
value
|
||
}) => {
|
||
if (type == 'addFolder') {
|
||
let fileAllPathName = this.folderCurrent + '/' + value;
|
||
$http.post(`file_manager/directories`, {
|
||
name: fileAllPathName
|
||
}).then((res) => {
|
||
layer.msg(res.message)
|
||
node.expanded = true
|
||
this.$refs.tree.append({
|
||
name: value,
|
||
path: fileAllPathName,
|
||
leaf: true
|
||
}, node);
|
||
this.$refs.tree.setCurrentKey(fileAllPathName)
|
||
this.folderCurrent = fileAllPathName;
|
||
this.images = [];
|
||
this.image_page = 1
|
||
this.image_total = 0
|
||
this.updateDefaultExpandedKeys(node.data, 'expand')
|
||
})
|
||
}
|
||
|
||
if (type == 'renameFolder') {
|
||
this.folderCurrent = data.path;
|
||
|
||
$http.post(`file_manager/rename`, {
|
||
origin_name: data.path,
|
||
new_name: value
|
||
}).then((res) => {
|
||
layer.msg(res.message)
|
||
data.name = value;
|
||
data.path = data.path.replace(/\/[^\/]*$/, '/' + value);
|
||
this.folderCurrent = this.folderCurrent.replace(/\/[^\/]*$/, '/' + value);
|
||
// 递归修改 data 内所有 children -> path 的对应 level = value
|
||
this.changeChildren(data, node, value);
|
||
})
|
||
}
|
||
|
||
if (type == 'image') {
|
||
const name = this.images[this.selectImageIndex].name;
|
||
const origin_name = this.folderCurrent == '/' ? '/' + name : this.folderCurrent + '/' + name;
|
||
|
||
$http.post(`file_manager/rename`, {
|
||
origin_name: origin_name,
|
||
new_name: value + '.' + fileSuffix
|
||
}).then((res) => {
|
||
this.images[this.selectImageIndex].name = value + '.' + fileSuffix;
|
||
layer.msg(res.message)
|
||
})
|
||
}
|
||
}).catch(() => {});
|
||
},
|
||
|
||
changeChildren(data, node, value) {
|
||
if (data.children) {
|
||
data.children.map(e => {
|
||
if (e.path) {
|
||
// 将字符串转换为数组
|
||
let path = e.path.split('/')
|
||
path[node.level - 1] = value
|
||
// 将数组转换为字符串
|
||
e.path = path.join('/')
|
||
}
|
||
|
||
if (e.children) {
|
||
this.changeChildren(e, node, value)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
@stack('admin.file_manager.vue.method')
|
||
},
|
||
|
||
created() {
|
||
const defaultkeyarr = sessionStorage.getItem('defaultkeyarr');
|
||
const folderCurrent = sessionStorage.getItem('folderCurrent');
|
||
|
||
if (defaultkeyarr) {
|
||
this.defaultkeyarr = defaultkeyarr.split(',');
|
||
}
|
||
|
||
if (folderCurrent) {
|
||
this.folderCurrent = folderCurrent;
|
||
}
|
||
},
|
||
// 实例被挂载后调用
|
||
mounted() {
|
||
this.loadData()
|
||
// 获取键盘事件 是否按住 shift/ctrl 键 兼容 mac 和 windows
|
||
document.addEventListener('keydown', (e) => {
|
||
this.isShift = e.shiftKey;
|
||
this.isCtrl = e.ctrlKey || e.metaKey;
|
||
})
|
||
|
||
// 获取键盘事件 是否松开 shift/ctrl 键
|
||
document.addEventListener('keyup', (e) => {
|
||
this.isShift = e.shiftKey;
|
||
this.isCtrl = e.ctrlKey || e.metaKey;
|
||
})
|
||
|
||
// 判断鼠标是否点击 .image-list 元素
|
||
document.addEventListener('click', (e) => {
|
||
if (this.isBatchSelect) return;
|
||
const targets = ['filemanager-navbar', 'content-center']
|
||
if (targets.indexOf(e.target.className) > -1) {
|
||
this.selectImageIndex = [];
|
||
this.images.map(e => e.selected = false)
|
||
}
|
||
})
|
||
},
|
||
})
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|