文档管理
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.

522 lines
13 KiB

6 months ago
<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 }"
6 months ago
@click="onCrumb(item)"
6 months ago
>{{ item.name }}</el-breadcrumb-item
>
</template>
</el-breadcrumb>
</template>
<EdfsContextMenu
eventSourceClass="SourceClass"
:disabledEmpty="false"
@visibleChange="onVisibleChange"
ref="contextMenuRef"
:menuList="dropdownMenu"
@beforeContextmenu="onBeforeContextmenu"
6 months ago
>
6 months ago
<div class="file-list">
6 months ago
<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">
6 months ago
<img
:src="
item.type === floeType.folder
? Folder
: item.isDraft === 0
? Document
: Document2
"
/>
6 months ago
</div>
<div class="file-name">
<el-input
class="edit-input"
@click.stop="() => {}"
6 months ago
v-if="!!item?.isEdit"
6 months ago
v-model="editFileName"
6 months ago
:key="item.id + '_edit'"
6 months ago
:ref="el => setInputRefs(el, item.id)"
@blur="onSaveRename(item)"
6 months ago
@keyup.enter="onSaveRename(item)"
6 months ago
/>
6 months ago
<span v-else>{{ item.name }}</span>
6 months ago
</div>
</div>
</div>
</div>
<template #menu="{ eventData, menuData }">
6 months ago
<div
v-for="menu in menuData"
6 months ago
:key="menu.command"
@click="onCommand(menu.command, eventData)"
6 months ago
>
<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>
6 months ago
<markdownDrawer
v-model="isShowMdDrawer"
v-if="isShowMdDrawer"
:data="curMarkdown"
:isRootMd="isRootMd"
6 months ago
@onSave="onSaveMd"
/>
<UploadMDDlg
:is-show="isShowMdDlg"
@on-close="isShowMdDlg = false"
@on-save="onUpdatedMdSave"
/>
6 months ago
</template>
<script setup lang="ts">
6 months ago
import {
floeType,
operationDropdownMenu,
breadcrumbList,
fileDropdownMenu,
} from './utils'
6 months ago
import EdfsWrap from '@/components/dashboard/Edfs-wrap.vue'
6 months ago
import {
getFileList,
createFolder,
updateFolder,
createdFile,
updateFile,
deleteFolder,
deleteFile,
deleteFolderAndFile,
6 months ago
getMarkdown,
updateMarkdown,
type ContentType,
} from '@/api/module/eam/device/document'
6 months ago
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'
6 months ago
import Document2 from '@/assets/image/dashboard/file/document2.svg'
import UploadMDDlg from './components/uploadMDDlg.vue'
6 months ago
6 months ago
import { Icon } from '@/components/dashboard/Icon'
import EdfsContextMenu from '@/components/dashboard/Edfs-context-menu/index.vue'
6 months ago
import markdownDrawer from './components/markdownDrawer.vue'
6 months ago
const dropdownMenu = computed(() => {
if (isRootMd.value) {
return fileDropdownMenu.filter(v => v.command === 'open')
}
6 months ago
return menuTarget.value
? fileDropdownMenu
: currentFolderId.value === 0
? operationDropdownMenu.filter(v => v.command === 'newFolder')
: operationDropdownMenu.filter(v => ['uploadMD', 'newMarkdown'].includes(v.command))
6 months ago
})
const message = useMessage()
6 months ago
const currentFolderId = ref(0)
watch(
() => breadcrumbList.value.length,
() => {
currentFolderId.value = breadcrumbList.value[breadcrumbList.value.length - 1].id
}
)
6 months ago
const isRootMd = computed(
() => currentMenu.value?.type === floeType.file && currentFolderId.value === 0
)
6 months ago
const dataList = ref<any>([])
const loading = ref(false)
async function loadData(id: number = 0) {
loading.value = true
const res = await getFileList({
parentId: id,
})
6 months ago
loading.value = false
if (isResError(res)) {
// 错误 删除最后一个面包屑
if (breadcrumbList.value.length > 1) {
breadcrumbList.value.pop()
}
return
}
6 months ago
dataList.value = res.data
6 months ago
}
6 months ago
6 months ago
async function onDelete(item: any) {
6 months ago
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)
6 months ago
if (isResError(res)) return
message.success('删除成功')
6 months ago
loadData(currentFolderId.value)
6 months ago
} catch (error) {}
}
const contextMenuRef = ref<any>(null)
function onFile(e: any) {
contextMenuRef.value.onContextmenu(e)
}
function onNewFolder() {
const folder = {
6 months ago
name: '未命名文件夹',
6 months ago
type: floeType.folder,
6 months ago
isEdit: true,
}
dataList.value.push(folder)
onRename(folder)
}
function onNewMarkdown() {
const markdown = {
6 months ago
name: '未命名文档',
6 months ago
type: floeType.file,
6 months ago
isEdit: true,
}
dataList.value.push(markdown)
onRename(markdown)
}
const curCommand = ref('')
6 months ago
function onCommand(command: string, item: any) {
curCommand.value = command
6 months ago
switch (command) {
case 'delete':
6 months ago
onDelete(item)
6 months ago
break
case 'rename':
onRename(item)
break
case 'open':
onFileOpen(item)
break
case 'newFolder':
onNewFolder()
break
case 'newMarkdown':
onNewMarkdown()
break
case 'uploadMD':
onUpdatedMd(item)
6 months ago
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
}
}
6 months ago
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
}
6 months ago
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)
}
6 months ago
function onFileOpen(item: any) {
if (item.isEdit) return
6 months ago
if (item.type === floeType.folder) {
breadcrumbList.value.push(item)
loadData(item.id)
6 months ago
}
6 months ago
if (item.type === floeType.file) {
onOpenMarkdownDrawer(item.id)
6 months ago
}
}
const editInputRefs = ref<any>({})
function setInputRefs(el: any, id: number) {
if (el) {
editInputRefs.value[`editInputRef_${id}`] = el
}
}
const editFileName = ref('')
6 months ago
async function onSaveRename(item: any) {
6 months ago
const find = findItem(item.id)
if (!find.isEdit) return
await nextTick()
debugger
6 months ago
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)
}
6 months ago
editFileName.value = ''
}
async function onRename(item: any) {
if (!item) return
6 months ago
const find = findItem(item.id)
find.isEdit = true
editFileName.value = find.name
6 months ago
await nextTick()
editInputRefs.value[`editInputRef_${item.id}`].focus()
editInputRefs.value[`editInputRef_${item.id}`].select()
}
6 months ago
6 months ago
const findItem = (id: number) => dataList.value.find((v: any) => v.id === id)
6 months ago
async function onSaveFile(item: any) {
const isAdd = !item.id
6 months ago
loading.value = true
6 months ago
switch (item.type) {
case floeType.folder:
await saveFolder(isAdd, item)
break
case floeType.file:
await saveFile(isAdd, item)
break
}
6 months ago
loadData(currentFolderId.value)
}
function getPath() {
return currentFolderId.value === 0
? ''
: breadcrumbList.value[breadcrumbList.value.length - 1].path
6 months ago
}
async function saveFolder(isAdd: boolean, item: any) {
6 months ago
getPath()
6 months ago
let res
if (isAdd) {
res = await createFolder({
name: item.name,
6 months ago
parentId: currentFolderId.value,
path: getPath(),
6 months ago
})
} else {
res = await updateFolder({
id: item.id,
name: item.name,
6 months ago
parentId: currentFolderId.value,
path: getPath(),
6 months ago
})
}
6 months ago
if (isResError(res)) {
// 删除新增的文件夹
if (isAdd) {
dataList.value.pop()
}
return
}
6 months ago
}
async function saveFile(isAdd: boolean, item: any) {
let res
if (isAdd) {
res = await createdFile({
name: item.name,
6 months ago
parentId: currentFolderId.value,
isDraft: 1,
path: getPath(),
6 months ago
})
} else {
res = await updateFile({
id: item.id,
name: item.name,
6 months ago
parentId: currentFolderId.value,
path: getPath(),
6 months ago
})
}
if (isResError(res)) return ''
return res.data.id
6 months ago
}
6 months ago
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()
}
})
6 months ago
// markdown 操作
6 months ago
const curMarkdown = ref() as Ref<ContentType & { fileName: string }>
const curMdId = ref()
6 months ago
const isShowMdDrawer = ref(false)
async function onOpenMarkdownDrawer(id: number) {
6 months ago
curMdId.value = id
6 months ago
const res = await getMarkdown({ folderId: id })
if (isResError(res)) return
6 months ago
curMarkdown.value = Object.assign({}, res.data, { fileName: findItem(id).name })
6 months ago
isShowMdDrawer.value = true
}
async function onSaveMd(isDraft: 0 | 1, data: string) {
const res = await updateMarkdown({
content: data,
6 months ago
folderId: curMdId.value,
6 months ago
isDraft,
})
if (isResError(res)) return
message.success(isDraft === 1 ? '保存成功' : '发布成功')
isShowMdDrawer.value = false
curMarkdown.value = null as any
6 months ago
loadData(currentFolderId.value)
6 months ago
}
6 months ago
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>