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

410 lines
9.9 KiB

7 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 }"
7 months ago
@click="onCrumb(item)"
7 months ago
>{{ item.name }}</el-breadcrumb-item
>
</template>
</el-breadcrumb>
</template>
<EdfsContextMenu
eventSourceClass="SourceClass"
:disabledEmpty="false"
@visibleChange="onVisibleChange"
ref="contextMenuRef"
>
7 months ago
<div class="file-list" v-if="loading">
7 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">
7 months ago
<!-- {{ !!item.isEdit }} -->
<img :src="item.type === floeType.folder ? Folder : Document" />
7 months ago
</div>
<div class="file-name">
<el-input
class="edit-input"
@click.stop="() => {}"
7 months ago
v-if="!!item?.isEdit"
7 months ago
v-model="editFileName"
7 months ago
:key="item.id + '_edit'"
7 months ago
:ref="el => setInputRefs(el, item.id)"
@blur="onSaveRename(item)"
7 months ago
@keyup.enter="onSaveRename(item)"
7 months ago
/>
7 months ago
<span v-else>{{ item.name }}</span>
7 months ago
</div>
</div>
</div>
</div>
<template #menu="{ menuData }">
<div
v-for="menu in dropdownMenu"
:key="menu.command"
@click="onCommand(menu.command, menuData)"
>
<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>
7 months ago
<markdownDrawer
v-model="isShowMdDrawer"
v-if="isShowMdDrawer"
:data="curMarkdown"
@onSave="onSaveMd"
/>
7 months ago
</template>
<script setup lang="ts">
7 months ago
import {
floeType,
operationDropdownMenu,
breadcrumbList,
fileDropdownMenu,
} from './utils'
7 months ago
import EdfsWrap from '@/components/dashboard/Edfs-wrap.vue'
7 months ago
import {
getFileList,
createFolder,
updateFolder,
createdFile,
updateFile,
deleteFolder,
deleteFile,
getMarkdown,
updateMarkdown,
type ContentType,
} from '@/api/module/eam/device/document'
7 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'
import { Icon } from '@/components/dashboard/Icon'
import EdfsContextMenu from '@/components/dashboard/Edfs-context-menu/index.vue'
7 months ago
import markdownDrawer from './components/markdownDrawer.vue'
7 months ago
const dropdownMenu = computed(() => {
return menuTarget.value ? fileDropdownMenu : operationDropdownMenu
})
const message = useMessage()
7 months ago
const currentId = ref(0)
watch(breadcrumbList.value, () => {
currentId.value = breadcrumbList.value[breadcrumbList.value.length - 1].id
})
7 months ago
7 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,
})
if (isResError(res)) return
dataList.value = res.data.map((item: any) => ({
...item,
isEdit: false,
}))
loading.value = true
}
7 months ago
7 months ago
async function onDelete(item: any) {
7 months ago
try {
7 months ago
let res
7 months ago
await message.delConfirm()
7 months ago
switch (item.type) {
case floeType.folder:
res = await deleteFolder(item.id)
break
case floeType.file:
res = await deleteFile(item.id)
break
}
7 months ago
if (isResError(res)) return
message.success('删除成功')
7 months ago
loadData(currentId.value)
7 months ago
} catch (error) {}
}
const contextMenuRef = ref<any>(null)
function onFile(e: any) {
contextMenuRef.value.onContextmenu(e)
}
function onNewFolder() {
const folder = {
name: '新建文件夹',
7 months ago
type: floeType.folder,
7 months ago
isEdit: true,
}
dataList.value.push(folder)
onRename(folder)
}
function onNewMarkdown() {
const markdown = {
name: '新建文档',
7 months ago
type: floeType.file,
7 months ago
isEdit: true,
}
dataList.value.push(markdown)
onRename(markdown)
}
function onCommand(command: string, item: any) {
switch (command) {
case 'delete':
7 months ago
onDelete(item)
7 months ago
break
case 'rename':
onRename(item)
break
case 'open':
onFileOpen(item)
break
case 'newFolder':
onNewFolder()
break
case 'newMarkdown':
onNewMarkdown()
break
case 'upload':
break
}
}
const menuTarget = ref<HTMLElement | null>(null)
function onVisibleChange(visible: boolean, currentElement: HTMLElement | null) {
menuTarget.value = currentElement
}
7 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)
}
7 months ago
function onFileOpen(item: any) {
if (item.isEdit) return
7 months ago
if (item.type === floeType.folder) {
breadcrumbList.value.push(item)
loadData(item.id)
7 months ago
}
7 months ago
if (item.type === floeType.file) {
onOpenMarkdownDrawer(item.id)
7 months ago
}
}
const editInputRefs = ref<any>({})
function setInputRefs(el: any, id: number) {
if (el) {
editInputRefs.value[`editInputRef_${id}`] = el
}
}
const editFileName = ref('')
7 months ago
async function onSaveRename(item: any) {
if (!item.isEdit) return
item.name = editFileName.value
await nextTick()
7 months ago
item.isEdit = false
7 months ago
await nextTick()
await onSaveFile(item)
7 months ago
editFileName.value = ''
}
async function onRename(item: any) {
if (!item) return
item.isEdit = true
7 months ago
await nextTick()
7 months ago
editFileName.value = item.name
await nextTick()
editInputRefs.value[`editInputRef_${item.id}`].focus()
editInputRefs.value[`editInputRef_${item.id}`].select()
}
7 months ago
async function onSaveFile(item: any) {
const isAdd = !item.id
switch (item.type) {
case floeType.folder:
await saveFolder(isAdd, item)
break
case floeType.file:
await saveFile(isAdd, item)
break
}
loadData(currentId.value)
}
async function saveFolder(isAdd: boolean, item: any) {
let res
if (isAdd) {
res = await createFolder({
name: item.name,
parentId: currentId.value,
})
} else {
res = await updateFolder({
id: item.id,
name: item.name,
parentId: currentId.value,
})
}
if (isResError(res)) return
}
async function saveFile(isAdd: boolean, item: any) {
let res
if (isAdd) {
res = await createdFile({
name: item.name + '.md',
parentId: currentId.value,
})
} else {
res = await updateFile({
id: item.id,
name: item.name,
parentId: currentId.value,
})
}
if (isResError(res)) return
}
// markdown 操作
const curMarkdown = ref() as Ref<ContentType>
const isShowMdDrawer = ref(false)
async function onOpenMarkdownDrawer(id: number) {
const res = await getMarkdown({ folderId: id })
if (isResError(res)) return
curMarkdown.value = res?.data
isShowMdDrawer.value = true
}
async function onSaveMd(isDraft: 0 | 1, data: string) {
const res = await updateMarkdown({
content: data,
folderId: currentId.value,
id: curMarkdown.value?.id,
isDraft,
})
if (isResError(res)) return
message.success(isDraft === 1 ? '保存成功' : '发布成功')
isShowMdDrawer.value = false
curMarkdown.value = null as any
loadData(currentId.value)
}
7 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>