admin-vue3/src/views/flow/FileManager.vue

399 lines
7.4 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

<template>
<div class="file-manager">
<!-- 左侧菜单 -->
<div class="sidebar">
<!-- Logo -->
<div class="logo">
<router-link to="/" class="back-btn">
<i class="icon"></i>
</router-link>
<img src="@/assets/logo.svg" alt="Logo"/>
<span>Flow Design</span>
</div>
<!-- 新建按钮组 -->
<div class="action-buttons">
<button class="btn-new" @click="handleCreate">
<i class="icon">+</i>
新建
</button>
<button class="btn-template" @click="openTemplateDialog">
<i class="icon">📋</i>
从模板新建
</button>
</div>
<!-- 菜单列表 -->
<nav class="menu-list">
<router-link
to="/files/my-files"
class="menu-item"
active-class="active"
>
<i class="icon">📁</i>
我的文件
</router-link>
<router-link
to="/files/favorites"
class="menu-item"
active-class="active"
>
<i class="icon"></i>
我的收藏
</router-link>
<router-link
to="/files/recent"
class="menu-item"
active-class="active"
>
<i class="icon">🕒</i>
最近
</router-link>
<div class="menu-divider"></div>
<router-link
to="/files/recommended"
class="menu-item"
active-class="active"
>
<i class="icon">🔥</i>
推荐
</router-link>
<router-link
to="/files/community"
class="menu-item"
active-class="active"
>
<i class="icon">👥</i>
社区
</router-link>
<div class="menu-divider"></div>
<router-link
to="/files/trash"
class="menu-item"
active-class="active"
>
<i class="icon">🗑</i>
回收站
</router-link>
</nav>
</div>
<!-- 右侧内容区 -->
<div class="content">
<!-- 顶部搜索栏 -->
<div class="search-bar">
<div class="search-input">
<i class="icon">🔍</i>
<input type="text" placeholder="搜索文件"/>
</div>
<div class="view-options">
<button class="btn-view active">
<i class="icon">📊</i>
</button>
<button class="btn-view">
<i class="icon">📋</i>
</button>
</div>
</div>
<!-- 路由出口 -->
<router-view/>
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import nodesData from '@/assets/data/nodes.json'
import businessProcess from '@/assets/examples/business-process.svg'
import mindMap from '@/assets/examples/mind-map.svg'
import umlDiagram from '@/assets/examples/uml.svg'
import orgChart from '@/assets/examples/org-chart.svg'
import defaultAvatar from '@/assets/avatars/default-avatar.svg'
const router = useRouter()
// 图片映射
const previewMap = {
'business-process': businessProcess,
'mind-map': mindMap,
'uml': umlDiagram,
'org-chart': orgChart,
'default-avatar': defaultAvatar
}
// 提供给子组件的数据
const processedData = {
files: nodesData.files.map(file => ({
...file,
preview: previewMap[file.preview as keyof typeof previewMap]
})),
templates: nodesData.templates.map(template => ({
...template,
preview: previewMap[template.preview as keyof typeof previewMap]
})),
communityItems: nodesData.communityItems.map(item => ({
...item,
preview: previewMap[item.preview as keyof typeof previewMap],
authorAvatar: previewMap[item.authorAvatar as keyof typeof previewMap]
})),
deletedFiles: nodesData.deletedFiles.map(file => ({
...file,
preview: previewMap[file.preview as keyof typeof previewMap]
}))
}
// 导出处理后的数据供子组件使用
defineExpose(processedData)
const handleCreate = () => {
router.push('/flow-editor')
}
const openTemplateDialog = () => {
router.push('/flow-editor')
}
</script>
<style scoped>
.file-manager {
display: flex;
min-height: 100vh;
width: 100vw;
background: #fff;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.sidebar {
width: 240px;
min-width: 240px;
background: #fff;
border-right: 1px solid #e4e7ed;
padding: 20px;
display: flex;
flex-direction: column;
height: 100%;
overflow-y: auto;
}
.logo {
display: flex;
align-items: center;
gap: 8px;
padding: 0 12px;
margin-bottom: 24px;
}
.logo img {
height: 32px;
}
.logo span {
font-size: 18px;
font-weight: 600;
color: #1a1a1a;
}
.action-buttons {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 24px;
}
.btn-new, .btn-template {
display: flex;
align-items: center;
gap: 8px;
padding: 12px;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
}
.btn-new {
background: #409eff;
color: #fff;
}
.btn-new:hover {
background: #66b1ff;
}
.btn-template {
background: #f5f7fa;
color: #606266;
}
.btn-template:hover {
background: #e4e7ed;
}
.menu-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.menu-item {
display: flex;
align-items: center;
gap: 8px;
padding: 12px;
border-radius: 6px;
color: #606266;
text-decoration: none;
transition: all 0.2s;
}
.menu-item:hover {
background: #f5f7fa;
}
.menu-item.active {
background: #ecf5ff;
color: #409eff;
}
.menu-divider {
height: 1px;
background: #e4e7ed;
margin: 12px 0;
}
.content {
flex: 1;
padding: 20px;
background: #f5f7fa;
overflow-y: auto;
height: 100%;
width: calc(100% - 240px);
}
.search-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.search-input {
display: flex;
align-items: center;
gap: 8px;
background: #fff;
padding: 8px 16px;
border-radius: 6px;
width: 300px;
}
.search-input input {
border: none;
outline: none;
font-size: 14px;
width: 100%;
}
.view-options {
display: flex;
gap: 8px;
}
.btn-view {
padding: 8px;
border: none;
border-radius: 4px;
background: #fff;
cursor: pointer;
transition: all 0.2s;
}
.btn-view:hover, .btn-view.active {
background: #ecf5ff;
color: #409eff;
}
.file-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
.file-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
transition: transform 0.2s;
}
.file-card:hover {
transform: translateY(-2px);
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.file-preview {
aspect-ratio: 16/9;
background: #f5f7fa;
}
.file-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
.file-info {
padding: 12px;
}
.file-info h3 {
font-size: 14px;
font-weight: 500;
color: #1a1a1a;
margin-bottom: 4px;
}
.file-info p {
font-size: 12px;
color: #909399;
}
.back-btn {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
border-radius: 4px;
color: #606266;
text-decoration: none;
transition: all 0.2s;
}
.back-btn:hover {
background: #f5f7fa;
color: #409eff;
}
@media (max-width: 768px) {
.sidebar {
width: 200px;
min-width: 200px;
}
.content {
width: calc(100% - 200px);
}
.search-input {
width: 200px;
}
}
</style>