You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
521 lines
13 KiB
521 lines
13 KiB
<template> |
|
<div class="firmware-management-wrap"> |
|
<EdfsWrap class="firmware-table" :customLeft="true"> |
|
<template #title-left> |
|
<el-breadcrumb :separator-icon="ArrowRight"> |
|
<template v-for="(item, index) in breadcrumbList" :key="index"> |
|
<el-breadcrumb-item |
|
:class="{ active: index + 1 < breadcrumbList.length }" |
|
@click="onCrumb(item)" |
|
>{{ item.name }}</el-breadcrumb-item |
|
> |
|
</template> |
|
</el-breadcrumb> |
|
</template> |
|
<EdfsContextMenu |
|
eventSourceClass="SourceClass" |
|
:disabledEmpty="false" |
|
@visibleChange="onVisibleChange" |
|
ref="contextMenuRef" |
|
:menuList="dropdownMenu" |
|
@beforeContextmenu="onBeforeContextmenu" |
|
> |
|
<div class="file-list"> |
|
<div v-for="item in dataList" :key="item.id" @click="onFileOpen(item)"> |
|
<div class="item SourceClass" v-setItem="item"> |
|
<div class="file-header"> |
|
<div></div> |
|
<Icon |
|
class="icon" |
|
icon="solar:hamburger-menu-outline" |
|
@click="onFile" |
|
></Icon> |
|
</div> |
|
<div class="file-icon"> |
|
<img |
|
:src=" |
|
item.type === floeType.folder |
|
? Folder |
|
: item.isDraft === 0 |
|
? Document |
|
: Document2 |
|
" |
|
/> |
|
</div> |
|
<div class="file-name"> |
|
<el-input |
|
class="edit-input" |
|
@click.stop="() => {}" |
|
v-if="!!item?.isEdit" |
|
v-model="editFileName" |
|
:key="item.id + '_edit'" |
|
:ref="el => setInputRefs(el, item.id)" |
|
@blur="onSaveRename(item)" |
|
@keyup.enter="onSaveRename(item)" |
|
/> |
|
<span v-else>{{ item.name }}</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<template #menu="{ eventData, menuData }"> |
|
<div |
|
v-for="menu in menuData" |
|
:key="menu.command" |
|
@click="onCommand(menu.command, eventData)" |
|
> |
|
<img |
|
v-if="menu?.icon" |
|
:src="menu?.icon" |
|
width="20" |
|
style="margin-right: 8px" |
|
/> |
|
<span :style="{ color: menu.command === 'delete' ? 'red' : 'inherit' }">{{ |
|
menu.label |
|
}}</span> |
|
</div> |
|
</template> |
|
</EdfsContextMenu> |
|
</EdfsWrap> |
|
</div> |
|
<markdownDrawer |
|
v-model="isShowMdDrawer" |
|
v-if="isShowMdDrawer" |
|
:data="curMarkdown" |
|
:isRootMd="isRootMd" |
|
@onSave="onSaveMd" |
|
/> |
|
<UploadMDDlg |
|
:is-show="isShowMdDlg" |
|
@on-close="isShowMdDlg = false" |
|
@on-save="onUpdatedMdSave" |
|
/> |
|
</template> |
|
|
|
<script setup lang="ts"> |
|
import { |
|
floeType, |
|
operationDropdownMenu, |
|
breadcrumbList, |
|
fileDropdownMenu, |
|
} from './utils' |
|
import EdfsWrap from '@/components/dashboard/Edfs-wrap.vue' |
|
import { |
|
getFileList, |
|
createFolder, |
|
updateFolder, |
|
createdFile, |
|
updateFile, |
|
deleteFolder, |
|
deleteFile, |
|
deleteFolderAndFile, |
|
getMarkdown, |
|
updateMarkdown, |
|
type ContentType, |
|
} from '@/api/module/eam/device/document' |
|
import { isResError, useMessage } from '@/hooks/useMessage.js' |
|
import { ArrowRight } from '@element-plus/icons-vue' |
|
import Folder from '@/assets/image/dashboard/file/folder.svg' |
|
import Upload from '@/assets/image/dashboard/file/upload.svg' |
|
import Document from '@/assets/image/dashboard/file/document.svg' |
|
import Document2 from '@/assets/image/dashboard/file/document2.svg' |
|
import UploadMDDlg from './components/uploadMDDlg.vue' |
|
|
|
import { Icon } from '@/components/dashboard/Icon' |
|
import EdfsContextMenu from '@/components/dashboard/Edfs-context-menu/index.vue' |
|
import markdownDrawer from './components/markdownDrawer.vue' |
|
|
|
const dropdownMenu = computed(() => { |
|
if (isRootMd.value) { |
|
return fileDropdownMenu.filter(v => v.command === 'open') |
|
} |
|
return menuTarget.value |
|
? fileDropdownMenu |
|
: currentFolderId.value === 0 |
|
? operationDropdownMenu.filter(v => v.command === 'newFolder') |
|
: operationDropdownMenu.filter(v => ['uploadMD', 'newMarkdown'].includes(v.command)) |
|
}) |
|
|
|
const message = useMessage() |
|
|
|
const currentFolderId = ref(0) |
|
watch( |
|
() => breadcrumbList.value.length, |
|
() => { |
|
currentFolderId.value = breadcrumbList.value[breadcrumbList.value.length - 1].id |
|
} |
|
) |
|
|
|
const isRootMd = computed( |
|
() => currentMenu.value?.type === floeType.file && currentFolderId.value === 0 |
|
) |
|
|
|
const dataList = ref<any>([]) |
|
const loading = ref(false) |
|
async function loadData(id: number = 0) { |
|
loading.value = true |
|
const res = await getFileList({ |
|
parentId: id, |
|
}) |
|
loading.value = false |
|
if (isResError(res)) { |
|
// 错误 删除最后一个面包屑 |
|
if (breadcrumbList.value.length > 1) { |
|
breadcrumbList.value.pop() |
|
} |
|
return |
|
} |
|
dataList.value = res.data |
|
} |
|
|
|
async function onDelete(item: any) { |
|
try { |
|
await message.delConfirm() |
|
// switch (item.type) { |
|
// case floeType.folder: |
|
// res = await deleteFolder(item.id) |
|
// break |
|
// case floeType.file: |
|
// res = await deleteFile(item.id) |
|
// break |
|
// } |
|
const res = await deleteFolderAndFile(item.id) |
|
|
|
if (isResError(res)) return |
|
message.success('删除成功') |
|
loadData(currentFolderId.value) |
|
} catch (error) {} |
|
} |
|
|
|
const contextMenuRef = ref<any>(null) |
|
function onFile(e: any) { |
|
contextMenuRef.value.onContextmenu(e) |
|
} |
|
|
|
function onNewFolder() { |
|
const folder = { |
|
name: '未命名文件夹', |
|
type: floeType.folder, |
|
isEdit: true, |
|
} |
|
dataList.value.push(folder) |
|
onRename(folder) |
|
} |
|
|
|
function onNewMarkdown() { |
|
const markdown = { |
|
name: '未命名文档', |
|
type: floeType.file, |
|
isEdit: true, |
|
} |
|
dataList.value.push(markdown) |
|
onRename(markdown) |
|
} |
|
const curCommand = ref('') |
|
function onCommand(command: string, item: any) { |
|
curCommand.value = command |
|
switch (command) { |
|
case 'delete': |
|
onDelete(item) |
|
break |
|
case 'rename': |
|
onRename(item) |
|
break |
|
case 'open': |
|
onFileOpen(item) |
|
break |
|
case 'newFolder': |
|
onNewFolder() |
|
break |
|
case 'newMarkdown': |
|
onNewMarkdown() |
|
break |
|
case 'uploadMD': |
|
onUpdatedMd(item) |
|
break |
|
} |
|
} |
|
|
|
const isShowMdDlg = ref(false) |
|
function onUpdatedMd(item: any) { |
|
isShowMdDlg.value = true |
|
} |
|
|
|
async function onUpdatedMdSave(fileName: string, fileContent: string) { |
|
const id = await saveFile(true, { |
|
name: fileName, |
|
type: floeType.file, |
|
}) |
|
if (id) { |
|
curMdId.value = id |
|
curMarkdown.value = { |
|
fileName: fileName, |
|
content: fileContent, |
|
} as ContentType & { fileName: string } |
|
isShowMdDrawer.value = true |
|
} |
|
} |
|
|
|
const menuTarget = ref<HTMLElement | null>(null) |
|
function onVisibleChange(visible: boolean, currentElement: HTMLElement | null) { |
|
menuTarget.value = currentElement |
|
} |
|
|
|
const currentMenu = ref<any>(null) |
|
|
|
function onBeforeContextmenu(item: any) { |
|
currentMenu.value = item |
|
} |
|
|
|
function onCrumb(item: any) { |
|
const isLast = breadcrumbList.value[breadcrumbList.value.length - 1].id === item.id |
|
if (isLast) return |
|
const index = breadcrumbList.value.findIndex(v => v.id === item.id) |
|
breadcrumbList.value = breadcrumbList.value.slice(0, index + 1) |
|
loadData(item.id) |
|
} |
|
|
|
function onFileOpen(item: any) { |
|
if (item.isEdit) return |
|
if (item.type === floeType.folder) { |
|
breadcrumbList.value.push(item) |
|
loadData(item.id) |
|
} |
|
if (item.type === floeType.file) { |
|
onOpenMarkdownDrawer(item.id) |
|
} |
|
} |
|
|
|
const editInputRefs = ref<any>({}) |
|
function setInputRefs(el: any, id: number) { |
|
if (el) { |
|
editInputRefs.value[`editInputRef_${id}`] = el |
|
} |
|
} |
|
|
|
const editFileName = ref('') |
|
async function onSaveRename(item: any) { |
|
const find = findItem(item.id) |
|
if (!find.isEdit) return |
|
await nextTick() |
|
debugger |
|
find.isEdit = false |
|
if (find.type === floeType.file && !editFileName.value.endsWith('.md')) { |
|
editFileName.value += '.md' |
|
} |
|
if (find.name !== editFileName.value) { |
|
find.name = editFileName.value |
|
await onSaveFile(find) |
|
} |
|
|
|
editFileName.value = '' |
|
} |
|
async function onRename(item: any) { |
|
if (!item) return |
|
const find = findItem(item.id) |
|
find.isEdit = true |
|
editFileName.value = find.name |
|
await nextTick() |
|
editInputRefs.value[`editInputRef_${item.id}`].focus() |
|
editInputRefs.value[`editInputRef_${item.id}`].select() |
|
} |
|
|
|
const findItem = (id: number) => dataList.value.find((v: any) => v.id === id) |
|
|
|
async function onSaveFile(item: any) { |
|
const isAdd = !item.id |
|
loading.value = true |
|
switch (item.type) { |
|
case floeType.folder: |
|
await saveFolder(isAdd, item) |
|
break |
|
case floeType.file: |
|
await saveFile(isAdd, item) |
|
break |
|
} |
|
|
|
loadData(currentFolderId.value) |
|
} |
|
|
|
function getPath() { |
|
return currentFolderId.value === 0 |
|
? '' |
|
: breadcrumbList.value[breadcrumbList.value.length - 1].path |
|
} |
|
|
|
async function saveFolder(isAdd: boolean, item: any) { |
|
getPath() |
|
let res |
|
if (isAdd) { |
|
res = await createFolder({ |
|
name: item.name, |
|
parentId: currentFolderId.value, |
|
path: getPath(), |
|
}) |
|
} else { |
|
res = await updateFolder({ |
|
id: item.id, |
|
name: item.name, |
|
parentId: currentFolderId.value, |
|
path: getPath(), |
|
}) |
|
} |
|
if (isResError(res)) { |
|
// 删除新增的文件夹 |
|
if (isAdd) { |
|
dataList.value.pop() |
|
} |
|
return |
|
} |
|
} |
|
async function saveFile(isAdd: boolean, item: any) { |
|
let res |
|
if (isAdd) { |
|
res = await createdFile({ |
|
name: item.name, |
|
parentId: currentFolderId.value, |
|
isDraft: 1, |
|
path: getPath(), |
|
}) |
|
} else { |
|
res = await updateFile({ |
|
id: item.id, |
|
name: item.name, |
|
parentId: currentFolderId.value, |
|
path: getPath(), |
|
}) |
|
} |
|
if (isResError(res)) return '' |
|
return res.data.id |
|
} |
|
|
|
const fullscreenLoading = ref() |
|
|
|
function openFullScreen() { |
|
fullscreenLoading.value = ElLoading.service({ |
|
lock: true, |
|
text: '数据加载中请稍等...', |
|
target: document.querySelector('.firmware-management-wrap') as HTMLElement, |
|
}) |
|
} |
|
watch(loading, val => { |
|
if (val) { |
|
openFullScreen() |
|
} else { |
|
fullscreenLoading.value?.close() |
|
} |
|
}) |
|
|
|
// markdown 操作 |
|
const curMarkdown = ref() as Ref<ContentType & { fileName: string }> |
|
const curMdId = ref() |
|
|
|
const isShowMdDrawer = ref(false) |
|
async function onOpenMarkdownDrawer(id: number) { |
|
curMdId.value = id |
|
const res = await getMarkdown({ folderId: id }) |
|
if (isResError(res)) return |
|
curMarkdown.value = Object.assign({}, res.data, { fileName: findItem(id).name }) |
|
|
|
isShowMdDrawer.value = true |
|
} |
|
|
|
async function onSaveMd(isDraft: 0 | 1, data: string) { |
|
const res = await updateMarkdown({ |
|
content: data, |
|
folderId: curMdId.value, |
|
isDraft, |
|
}) |
|
|
|
if (isResError(res)) return |
|
message.success(isDraft === 1 ? '保存成功' : '发布成功') |
|
isShowMdDrawer.value = false |
|
curMarkdown.value = null as any |
|
loadData(currentFolderId.value) |
|
} |
|
onMounted(() => { |
|
loadData() |
|
}) |
|
</script> |
|
|
|
<style scoped lang="scss"> |
|
.firmware-management-wrap { |
|
width: 100%; |
|
height: 100%; |
|
:deep(.el-breadcrumb) { |
|
margin-left: 4px; |
|
} |
|
.active { |
|
:deep(.el-breadcrumb__inner) { |
|
color: var(--el-color-primary); |
|
font-weight: 800; |
|
cursor: pointer; |
|
} |
|
} |
|
.file-list { |
|
user-select: none; |
|
display: flex; |
|
flex-wrap: wrap; |
|
gap: 20px; |
|
.item { |
|
width: 90px; |
|
height: 110px; |
|
display: flex; |
|
cursor: pointer; |
|
align-items: center; |
|
flex-direction: column; |
|
justify-content: center; |
|
border-radius: 3px; |
|
padding-bottom: 4px; |
|
.file-header { |
|
visibility: hidden; |
|
width: 100%; |
|
height: calc(100% - 66px - 24px); |
|
display: flex; |
|
align-items: center; |
|
padding: 0 8px; |
|
box-sizing: border-box; |
|
justify-content: space-between; |
|
.icon { |
|
flex-direction: end; |
|
color: var(--icon-color); |
|
:hover { |
|
color: var(--icon-hover-color); |
|
} |
|
} |
|
} |
|
|
|
.file-icon { |
|
width: 66px; |
|
height: 66px; |
|
img { |
|
width: 100%; |
|
height: 100%; |
|
} |
|
} |
|
.file-name { |
|
height: 24px; |
|
line-height: 24px; |
|
font-size: 14px; |
|
color: var(--label-color); |
|
overflow: hidden; |
|
text-overflow: ellipsis; |
|
white-space: nowrap; |
|
width: 100%; |
|
text-align: center; |
|
.edit-input { |
|
width: 100%; |
|
height: 100%; |
|
margin-bottom: 4px; |
|
} |
|
} |
|
&:hover { |
|
background-color: var(--mask-bg); |
|
.file-header { |
|
visibility: visible; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
</style>
|
|
|