增加流程配置
12930
pnpm-lock.yaml
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="64" cy="64" r="64" fill="#E5E9F2"/>
|
||||||
|
<circle cx="64" cy="48" r="24" fill="#C0CCDA"/>
|
||||||
|
<path d="M64 80C42.464 80 24.572 92.436 16 110.444C24.572 121.564 43.36 128 64 128C84.64 128 103.428 121.564 112 110.444C103.428 92.436 85.536 80 64 80Z" fill="#C0CCDA"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 380 B |
|
|
@ -0,0 +1,51 @@
|
||||||
|
interface AccordionItem {
|
||||||
|
title: string;
|
||||||
|
type: 'form' | 'text';
|
||||||
|
content: FormItem[] | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormItem {
|
||||||
|
label: string;
|
||||||
|
type: 'text' | 'select';
|
||||||
|
value: string;
|
||||||
|
options?: { label: string; value: string; }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const accordionData: AccordionItem[] = [
|
||||||
|
{
|
||||||
|
title: '基本设置',
|
||||||
|
type: 'form',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
label: '名称',
|
||||||
|
type: 'text',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '类型',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
options: [
|
||||||
|
{ label: '类型1', value: 'type1' },
|
||||||
|
{ label: '类型2', value: 'type2' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '高级设置',
|
||||||
|
type: 'form',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
label: '配置项',
|
||||||
|
type: 'text',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '其他信息',
|
||||||
|
type: 'text',
|
||||||
|
content: '这是一些其他信息的描述文本'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "UML类图",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"type": "uml-class",
|
||||||
|
"name": "类",
|
||||||
|
"icon": "📦",
|
||||||
|
"template": {
|
||||||
|
"title": "类名",
|
||||||
|
"attributes": ["+ 属性1: string", "- 属性2: number"],
|
||||||
|
"methods": ["+ 方法1()", "# 方法2(param: string)"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "interface",
|
||||||
|
"name": "接口",
|
||||||
|
"icon": "🔌",
|
||||||
|
"template": {
|
||||||
|
"title": "接口名",
|
||||||
|
"methods": ["+ 方法1()", "+ 方法2()"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "思维导图",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"type": "topic",
|
||||||
|
"name": "主题",
|
||||||
|
"icon": "💡",
|
||||||
|
"template": {
|
||||||
|
"title": "主题"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "subtopic",
|
||||||
|
"name": "子主题",
|
||||||
|
"icon": "📝",
|
||||||
|
"template": {
|
||||||
|
"title": "子主题"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "网络拓扑",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"type": "server",
|
||||||
|
"name": "服务器",
|
||||||
|
"icon": "🖥️",
|
||||||
|
"template": {
|
||||||
|
"title": "Server",
|
||||||
|
"ip": "192.168.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "router",
|
||||||
|
"name": "路由器",
|
||||||
|
"icon": "📡",
|
||||||
|
"template": {
|
||||||
|
"title": "Router",
|
||||||
|
"ip": "192.168.1.254"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "业务流程图",
|
||||||
|
"preview": "business-process",
|
||||||
|
"modifiedDate": "2024-01-20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "思维导图",
|
||||||
|
"preview": "mind-map",
|
||||||
|
"modifiedDate": "2024-01-18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "UML类图",
|
||||||
|
"preview": "uml",
|
||||||
|
"modifiedDate": "2024-01-15"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "项目管理流程",
|
||||||
|
"description": "适用于项目规划和任务管理",
|
||||||
|
"preview": "business-process"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "组织架构图",
|
||||||
|
"description": "快速创建公司组织结构图",
|
||||||
|
"preview": "org-chart"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"communityItems": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "电商系统架构图",
|
||||||
|
"preview": "business-process",
|
||||||
|
"author": "张三",
|
||||||
|
"authorAvatar": "default-avatar",
|
||||||
|
"likes": 128,
|
||||||
|
"comments": 32
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deletedFiles": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "旧版流程图",
|
||||||
|
"preview": "business-process",
|
||||||
|
"deleteTime": "2024-03-10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<svg width="400" height="225" viewBox="0 0 400 225" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="400" height="225" fill="#F5F7FA"/>
|
||||||
|
<rect x="50" y="92.5" width="100" height="40" rx="4" fill="#409EFF"/>
|
||||||
|
<text x="100" y="117.5" text-anchor="middle" fill="white" font-size="14">开始</text>
|
||||||
|
<path d="M150 112.5H200" stroke="#409EFF" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="200" y="92.5" width="100" height="40" rx="4" fill="#409EFF"/>
|
||||||
|
<text x="250" y="117.5" text-anchor="middle" fill="white" font-size="14">处理</text>
|
||||||
|
<path d="M300 112.5H350" stroke="#409EFF" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
|
||||||
|
markerWidth="6" markerHeight="6" orient="auto">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#409EFF"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 859 B |
|
|
@ -0,0 +1,81 @@
|
||||||
|
<svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- 渐变背景 -->
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="skyGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#2c5edf;stop-opacity:1" />
|
||||||
|
<stop offset="100%" style="stop-color:#5b9fff;stop-opacity:1" />
|
||||||
|
</linearGradient>
|
||||||
|
<!-- 流程图连线动画 -->
|
||||||
|
<path id="flowPath1" d="M100,200 C200,200 300,300 400,300" />
|
||||||
|
<path id="flowPath2" d="M400,300 C500,300 600,200 700,200" />
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- 背景 -->
|
||||||
|
<rect width="100%" height="100%" fill="url(#skyGradient)" />
|
||||||
|
|
||||||
|
<!-- 装饰性圆点 -->
|
||||||
|
<g class="dots" fill="#ffffff" fill-opacity="0.1">
|
||||||
|
<circle cx="100" cy="100" r="2">
|
||||||
|
<animate attributeName="r" values="2;4;2" dur="3s" repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="300" cy="200" r="3">
|
||||||
|
<animate attributeName="r" values="3;5;3" dur="4s" repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="500" cy="150" r="2">
|
||||||
|
<animate attributeName="r" values="2;4;2" dur="3.5s" repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="700" cy="300" r="3">
|
||||||
|
<animate attributeName="r" values="3;5;3" dur="4.5s" repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 流程图节点和连线 -->
|
||||||
|
<g class="flow-elements">
|
||||||
|
<!-- 节点 -->
|
||||||
|
<rect x="80" y="180" width="40" height="40" rx="5" fill="#ffffff" opacity="0.2">
|
||||||
|
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="3s" repeatCount="indefinite" />
|
||||||
|
</rect>
|
||||||
|
<rect x="380" y="280" width="40" height="40" rx="5" fill="#ffffff" opacity="0.2">
|
||||||
|
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="3s" repeatCount="indefinite" />
|
||||||
|
</rect>
|
||||||
|
<rect x="680" y="180" width="40" height="40" rx="5" fill="#ffffff" opacity="0.2">
|
||||||
|
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="3s" repeatCount="indefinite" />
|
||||||
|
</rect>
|
||||||
|
|
||||||
|
<!-- 动态连线 -->
|
||||||
|
<g stroke="#ffffff" stroke-width="2" stroke-opacity="0.3" fill="none">
|
||||||
|
<path d="">
|
||||||
|
<animate
|
||||||
|
attributeName="d"
|
||||||
|
values="M120,200 C200,200 300,300 380,300;M120,200 C200,200 300,290 380,300;M120,200 C200,200 300,300 380,300"
|
||||||
|
dur="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
<path d="">
|
||||||
|
<animate
|
||||||
|
attributeName="d"
|
||||||
|
values="M420,300 C500,300 600,200 680,200;M420,300 C500,310 600,200 680,200;M420,300 C500,300 600,200 680,200"
|
||||||
|
dur="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 流动的点 -->
|
||||||
|
<circle r="3" fill="#ffffff">
|
||||||
|
<animateMotion
|
||||||
|
dur="3s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
path="M120,200 C200,200 300,300 380,300"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
<circle r="3" fill="#ffffff">
|
||||||
|
<animateMotion
|
||||||
|
dur="3s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
path="M420,300 C500,300 600,200 680,200"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="400" height="225" viewBox="0 0 400 225" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="400" height="225" fill="#F5F7FA"/>
|
||||||
|
<circle cx="200" cy="112.5" r="40" fill="#409EFF"/>
|
||||||
|
<text x="200" y="117.5" text-anchor="middle" fill="white" font-size="14">核心主题</text>
|
||||||
|
<circle cx="100" cy="72.5" r="30" fill="#67C23A"/>
|
||||||
|
<text x="100" y="77.5" text-anchor="middle" fill="white" font-size="12">分支1</text>
|
||||||
|
<circle cx="100" cy="152.5" r="30" fill="#67C23A"/>
|
||||||
|
<text x="100" y="157.5" text-anchor="middle" fill="white" font-size="12">分支2</text>
|
||||||
|
<circle cx="300" cy="72.5" r="30" fill="#67C23A"/>
|
||||||
|
<text x="300" y="77.5" text-anchor="middle" fill="white" font-size="12">分支3</text>
|
||||||
|
<circle cx="300" cy="152.5" r="30" fill="#67C23A"/>
|
||||||
|
<text x="300" y="157.5" text-anchor="middle" fill="white" font-size="12">分支4</text>
|
||||||
|
<path d="M160 112.5L130 72.5" stroke="#67C23A" stroke-width="2"/>
|
||||||
|
<path d="M160 112.5L130 152.5" stroke="#67C23A" stroke-width="2"/>
|
||||||
|
<path d="M240 112.5L270 72.5" stroke="#67C23A" stroke-width="2"/>
|
||||||
|
<path d="M240 112.5L270 152.5" stroke="#67C23A" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,13 @@
|
||||||
|
<svg width="400" height="225" viewBox="0 0 400 225" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="400" height="225" fill="#F5F7FA"/>
|
||||||
|
<rect x="150" y="22.5" width="100" height="40" rx="4" fill="#409EFF"/>
|
||||||
|
<text x="200" y="47.5" text-anchor="middle" fill="white" font-size="14">CEO</text>
|
||||||
|
<rect x="50" y="92.5" width="100" height="40" rx="4" fill="#67C23A"/>
|
||||||
|
<text x="100" y="117.5" text-anchor="middle" fill="white" font-size="14">技术部</text>
|
||||||
|
<rect x="250" y="92.5" width="100" height="40" rx="4" fill="#67C23A"/>
|
||||||
|
<text x="300" y="117.5" text-anchor="middle" fill="white" font-size="14">市场部</text>
|
||||||
|
<path d="M200 62.5V82.5" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<path d="M100 82.5V92.5" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<path d="M300 82.5V92.5" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<path d="M100 82.5H300" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 895 B |
|
|
@ -0,0 +1,10 @@
|
||||||
|
<svg width="400" height="225" viewBox="0 0 400 225" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="400" height="225" fill="#F5F7FA"/>
|
||||||
|
<rect x="100" y="42.5" width="200" height="140" rx="4" fill="white" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<line x1="100" y1="82.5" x2="300" y2="82.5" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<line x1="100" y1="142.5" x2="300" y2="142.5" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<text x="200" y="67.5" text-anchor="middle" fill="#409EFF" font-size="14" font-weight="bold">Class</text>
|
||||||
|
<text x="110" y="107.5" fill="#666666" font-size="12">- attribute1: Type</text>
|
||||||
|
<text x="110" y="127.5" fill="#666666" font-size="12">- attribute2: Type</text>
|
||||||
|
<text x="110" y="167.5" fill="#666666" font-size="12">+ method(): ReturnType</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 787 B |
|
|
@ -0,0 +1,14 @@
|
||||||
|
<svg width="1440" height="800" viewBox="0 0 1440 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 0H1440V800H0V0Z" fill="url(#paint0_linear)"/>
|
||||||
|
<g opacity="0.1">
|
||||||
|
<circle cx="720" cy="400" r="300" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<circle cx="720" cy="400" r="200" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
<circle cx="720" cy="400" r="100" stroke="#409EFF" stroke-width="2"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear" x1="0" y1="0" x2="1440" y2="800" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#ECF5FF"/>
|
||||||
|
<stop offset="1" stop-color="#E4E7ED"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 644 B |
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M15 2L28 15L15 28L2 15L15 2Z" stroke="#409EFF" stroke-width="0.5"/>
|
||||||
|
<circle cx="15" cy="15" r="2" fill="#409EFF"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 231 B |
|
|
@ -0,0 +1,43 @@
|
||||||
|
<svg width="800" height="600" viewBox="0 0 800 600" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- 背景装饰圆圈 -->
|
||||||
|
<circle cx="400" cy="300" r="250" stroke="white" stroke-width="2" stroke-opacity="0.1"/>
|
||||||
|
<circle cx="400" cy="300" r="200" stroke="white" stroke-width="2" stroke-opacity="0.1"/>
|
||||||
|
<circle cx="400" cy="300" r="150" stroke="white" stroke-width="2" stroke-opacity="0.1"/>
|
||||||
|
|
||||||
|
<!-- 流程图示意 -->
|
||||||
|
<g opacity="0.2">
|
||||||
|
<!-- 开始节点 -->
|
||||||
|
<circle cx="250" cy="200" r="30" fill="white"/>
|
||||||
|
|
||||||
|
<!-- 处理节点1 -->
|
||||||
|
<rect x="350" y="170" width="100" height="60" rx="4" fill="white"/>
|
||||||
|
|
||||||
|
<!-- 判断节点 -->
|
||||||
|
<path d="M500 200 L550 230 L500 260 L450 230 Z" fill="white"/>
|
||||||
|
|
||||||
|
<!-- 处理节点2 -->
|
||||||
|
<rect x="350" y="300" width="100" height="60" rx="4" fill="white"/>
|
||||||
|
|
||||||
|
<!-- 结束节点 -->
|
||||||
|
<circle cx="550" cy="330" r="30" fill="white"/>
|
||||||
|
|
||||||
|
<!-- 连接线 -->
|
||||||
|
<path d="M280 200 H350" stroke="white" stroke-width="2"/>
|
||||||
|
<path d="M450 200 H450" stroke="white" stroke-width="2"/>
|
||||||
|
<path d="M550 230 V330" stroke="white" stroke-width="2"/>
|
||||||
|
<path d="M500 230 H400 V300" stroke="white" stroke-width="2"/>
|
||||||
|
<path d="M450 330 H520" stroke="white" stroke-width="2"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 装饰点 -->
|
||||||
|
<circle cx="200" cy="150" r="4" fill="white" fill-opacity="0.3"/>
|
||||||
|
<circle cx="600" cy="450" r="4" fill="white" fill-opacity="0.3"/>
|
||||||
|
<circle cx="150" cy="400" r="4" fill="white" fill-opacity="0.3"/>
|
||||||
|
<circle cx="650" cy="200" r="4" fill="white" fill-opacity="0.3"/>
|
||||||
|
|
||||||
|
<!-- 装饰线 -->
|
||||||
|
<line x1="100" y1="100" x2="150" y2="150" stroke="white" stroke-opacity="0.1"/>
|
||||||
|
<line x1="700" y1="500" x2="650" y2="450" stroke="white" stroke-opacity="0.1"/>
|
||||||
|
<line x1="100" y1="500" x2="150" y2="450" stroke="white" stroke-opacity="0.1"/>
|
||||||
|
<line x1="700" y1="100" x2="650" y2="150" stroke="white" stroke-opacity="0.1"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="4" y="4" width="24" height="24" rx="4" fill="#409EFF"/>
|
||||||
|
<path d="M10 16H22M16 10V22" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 258 B |
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* 通用的文件列表横向布局样式 */
|
||||||
|
.file-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-card {
|
||||||
|
width: 280px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 496 B |
|
|
@ -200,103 +200,107 @@ const clear = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div>
|
||||||
:class="prefixCls"
|
<div
|
||||||
class="fixed right-0 top-[45%] h-40px w-40px cursor-pointer bg-[var(--el-color-primary)] text-center leading-40px"
|
:class="prefixCls"
|
||||||
@click="drawer = true"
|
class="fixed right-0 top-[45%] h-40px w-40px cursor-pointer bg-[var(--el-color-primary)] text-center leading-40px"
|
||||||
>
|
@click="drawer = true"
|
||||||
<Icon color="#fff" icon="ep:setting" />
|
>
|
||||||
</div>
|
<Icon color="#fff" icon="ep:setting" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px">
|
<ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
|
<span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<!-- 主题 -->
|
<!-- 主题 -->
|
||||||
<ElDivider>{{ t('setting.theme') }}</ElDivider>
|
<ElDivider>{{ t('setting.theme') }}</ElDivider>
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
|
|
||||||
<!-- 布局 -->
|
<!-- 布局 -->
|
||||||
<ElDivider>{{ t('setting.layout') }}</ElDivider>
|
<ElDivider>{{ t('setting.layout') }}</ElDivider>
|
||||||
<LayoutRadioPicker />
|
<LayoutRadioPicker />
|
||||||
|
|
||||||
<!-- 系统主题 -->
|
<!-- 系统主题 -->
|
||||||
<ElDivider>{{ t('setting.systemTheme') }}</ElDivider>
|
<ElDivider>{{ t('setting.systemTheme') }}</ElDivider>
|
||||||
<ColorRadioPicker
|
|
||||||
v-model="systemTheme"
|
|
||||||
:schema="[
|
|
||||||
'#409eff',
|
|
||||||
'#009688',
|
|
||||||
'#536dfe',
|
|
||||||
'#ff5c93',
|
|
||||||
'#ee4f12',
|
|
||||||
'#0096c7',
|
|
||||||
'#9c27b0',
|
|
||||||
'#ff9800'
|
|
||||||
]"
|
|
||||||
@change="setSystemTheme"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 头部主题 -->
|
|
||||||
<ElDivider>{{ t('setting.headerTheme') }}</ElDivider>
|
|
||||||
<ColorRadioPicker
|
|
||||||
v-model="headerTheme"
|
|
||||||
:schema="[
|
|
||||||
'#fff',
|
|
||||||
'#151515',
|
|
||||||
'#5172dc',
|
|
||||||
'#e74c3c',
|
|
||||||
'#24292e',
|
|
||||||
'#394664',
|
|
||||||
'#009688',
|
|
||||||
'#383f45'
|
|
||||||
]"
|
|
||||||
@change="setHeaderTheme"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 菜单主题 -->
|
|
||||||
<template v-if="layout !== 'top'">
|
|
||||||
<ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
|
|
||||||
<ColorRadioPicker
|
<ColorRadioPicker
|
||||||
v-model="menuTheme"
|
v-model="systemTheme"
|
||||||
|
:schema="[
|
||||||
|
'#409eff',
|
||||||
|
'#009688',
|
||||||
|
'#536dfe',
|
||||||
|
'#ff5c93',
|
||||||
|
'#ee4f12',
|
||||||
|
'#0096c7',
|
||||||
|
'#9c27b0',
|
||||||
|
'#ff9800'
|
||||||
|
]"
|
||||||
|
@change="setSystemTheme"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 头部主题 -->
|
||||||
|
<ElDivider>{{ t('setting.headerTheme') }}</ElDivider>
|
||||||
|
<ColorRadioPicker
|
||||||
|
v-model="headerTheme"
|
||||||
:schema="[
|
:schema="[
|
||||||
'#fff',
|
'#fff',
|
||||||
'#001529',
|
'#151515',
|
||||||
'#212121',
|
'#5172dc',
|
||||||
'#273352',
|
'#e74c3c',
|
||||||
'#191b24',
|
'#24292e',
|
||||||
'#383f45',
|
'#394664',
|
||||||
'#001628',
|
'#009688',
|
||||||
'#344058'
|
'#383f45'
|
||||||
]"
|
]"
|
||||||
@change="setMenuTheme"
|
@change="setHeaderTheme"
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 界面显示 -->
|
<!-- 菜单主题 -->
|
||||||
<ElDivider>{{ t('setting.interfaceDisplay') }}</ElDivider>
|
<template v-if="layout !== 'top'">
|
||||||
<InterfaceDisplay />
|
<ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
|
||||||
|
<ColorRadioPicker
|
||||||
|
v-model="menuTheme"
|
||||||
|
:schema="[
|
||||||
|
'#fff',
|
||||||
|
'#1e293b', // 深靛蓝(现代科技感)
|
||||||
|
'#2c3e50', // 午夜蓝(优雅深邃)
|
||||||
|
'#252b3a', // 深蓝灰(专业稳重)
|
||||||
|
'#2b2d42', // 深藏青(高端大气)
|
||||||
|
'#1a237e', // 靛蓝(科技感强)
|
||||||
|
'#263238', // 蓝灰(沉稳现代)
|
||||||
|
'#1f2937' // 石墨蓝(简约时尚)
|
||||||
|
]"
|
||||||
|
@change="setMenuTheme"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ElDivider />
|
<!-- 界面显示 -->
|
||||||
<div>
|
<ElDivider>{{ t('setting.interfaceDisplay') }}</ElDivider>
|
||||||
<ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
|
<InterfaceDisplay />
|
||||||
</div>
|
|
||||||
<div class="mt-5px">
|
<ElDivider />
|
||||||
<ElButton class="w-full" type="danger" @click="clear">
|
<div>
|
||||||
{{ t('setting.clearAndReset') }}
|
<ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
|
||||||
</ElButton>
|
</div>
|
||||||
</div>
|
<div class="mt-5px">
|
||||||
</ElDrawer>
|
<ElButton class="w-full" type="danger" @click="clear">
|
||||||
|
{{ t('setting.clearAndReset') }}
|
||||||
|
</ElButton>
|
||||||
|
</div>
|
||||||
|
</ElDrawer>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$prefix-cls: #{$namespace}-setting;
|
$prefix-cls: #{$namespace}-setting;
|
||||||
|
|
||||||
.#{$prefix-cls} {
|
.#{$prefix-cls} {
|
||||||
|
z-index: 1200;
|
||||||
border-radius: 6px 0 0 6px;
|
border-radius: 6px 0 0 6px;
|
||||||
z-index: 1200;/*修正没有z-index会被表格层覆盖,值不要超过4000*/
|
|
||||||
|
/* 修正没有z-index会被表格层覆盖,值不要超过4000 */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
|
|
||||||
--left-menu-min-width: 64px;
|
--left-menu-min-width: 64px;
|
||||||
|
|
||||||
--left-menu-bg-color: #001529;
|
--left-menu-bg-color: #1e293b;
|
||||||
|
|
||||||
--left-menu-bg-light-color: #0f2438;
|
--left-menu-bg-light-color: #2c3e50;
|
||||||
|
|
||||||
--left-menu-bg-active-color: var(--el-color-primary);
|
--left-menu-bg-active-color: var(--el-color-primary);
|
||||||
|
|
||||||
--left-menu-text-color: #bfcbd9;
|
--left-menu-text-color: #e2e8f0;
|
||||||
|
|
||||||
--left-menu-text-active-color: #fff;
|
--left-menu-text-active-color: #fff;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>联系我们</h2>
|
||||||
|
<p>这里是联系我们页面的内容。</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Contact'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 添加页面特定的样式 */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="features">
|
||||||
|
<div class="features-content">
|
||||||
|
<h2>功能特点</h2>
|
||||||
|
<div class="feature-grid">
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">📊</div>
|
||||||
|
<h3>丰富的图形库</h3>
|
||||||
|
<p>提供大量预设图形和模板,满足各类图表绘制需求</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">🔄</div>
|
||||||
|
<h3>实时协作</h3>
|
||||||
|
<p>支持多人同时编辑,实时同步变更</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">💾</div>
|
||||||
|
<h3>自动保存</h3>
|
||||||
|
<p>自动保存所有更改,永不丢失工作进度</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">📱</div>
|
||||||
|
<h3>跨平台支持</h3>
|
||||||
|
<p>支持桌面和移动设备,随时随地访问</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.features-content {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-card {
|
||||||
|
background: #fff;
|
||||||
|
padding: 32px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
font-size: 40px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,399 @@
|
||||||
|
<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></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-edit')
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTemplateDialog = () => {
|
||||||
|
router.push('/flow-edit')
|
||||||
|
}
|
||||||
|
</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>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<SplitPane>
|
||||||
|
<template #toolbar>
|
||||||
|
<FlowToolbar></FlowToolbar>
|
||||||
|
</template>
|
||||||
|
<template #left>
|
||||||
|
<FlowAccordion />
|
||||||
|
</template>
|
||||||
|
<template #center>
|
||||||
|
<FlowCanvas />
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<Accordion :items="accordionData" />
|
||||||
|
</template>
|
||||||
|
</SplitPane>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, provide } from 'vue'
|
||||||
|
import { Graph } from '@maxgraph/core'
|
||||||
|
import { SplitPane, Accordion, FlowAccordion, FlowCanvas, FlowToolbar } from '../components/wu-flow-lib'
|
||||||
|
import { accordionData } from '@/assets/data/accordion-data'
|
||||||
|
|
||||||
|
const graph = ref<Graph>()
|
||||||
|
provide('graph', graph)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<div class="flow-editor">
|
||||||
|
<!-- 顶部区域:菜单和工具栏 -->
|
||||||
|
<FlowHeader />
|
||||||
|
|
||||||
|
<!-- 主内容区域:左中右布局 -->
|
||||||
|
<div class="flow-content">
|
||||||
|
<!-- 左侧:节点库和风格库 -->
|
||||||
|
<div class="left-panel">
|
||||||
|
<ShapeLibrary />
|
||||||
|
<StyleLibrary />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 中间:画布 -->
|
||||||
|
<div class="center-panel">
|
||||||
|
<FlowCanvas />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧:属性面板 -->
|
||||||
|
<div class="right-panel">
|
||||||
|
<PropertyPanel />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import FlowHeader from '../components/wu-flow-lib/components/FlowHeader.vue'
|
||||||
|
import FlowCanvas from '../components/wu-flow-lib/components/FlowCanvas.vue'
|
||||||
|
import ShapeLibrary from '../components/wu-flow-lib/components/ShapeLibrary.vue'
|
||||||
|
import StyleLibrary from '../components/wu-flow-lib/components/StyleLibrary.vue'
|
||||||
|
import PropertyPanel from '../components/wu-flow-lib/components/PropertyPanel.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.flow-editor {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
width: 280px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-right: 1px solid #dcdfe6;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-panel {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel {
|
||||||
|
width: 300px;
|
||||||
|
border-left: 1px solid #dcdfe6;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
<template>
|
||||||
|
<div class="home">
|
||||||
|
<header class="header">
|
||||||
|
<nav class="nav">
|
||||||
|
<div class="logo">
|
||||||
|
<img src="@/assets/logo.svg" alt="Flow Design">
|
||||||
|
</div>
|
||||||
|
<div class="nav-links">
|
||||||
|
<router-link to="/home">首页</router-link>
|
||||||
|
<router-link to="/home/features">功能</router-link>
|
||||||
|
<router-link to="/home/pricing">价格</router-link>
|
||||||
|
<router-link to="/home/contact">联系我们</router-link>
|
||||||
|
</div>
|
||||||
|
<div class="auth-buttons">
|
||||||
|
<router-link to="/login" class="login-btn">登录</router-link>
|
||||||
|
<router-link to="/register" class="register-btn">注册</router-link>
|
||||||
|
<router-link to="/files" class="register-btn">设计</router-link>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
localStorage.setItem('token', '123456')
|
||||||
|
const token = localStorage.getItem('token')
|
||||||
|
if (token) {
|
||||||
|
router.push('/files')
|
||||||
|
}
|
||||||
|
console.log('onMounted')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo img {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo span {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a {
|
||||||
|
color: #606266;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 1rem;
|
||||||
|
transition: color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn, .register-btn {
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
color: #409eff;
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn:hover {
|
||||||
|
background: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-btn {
|
||||||
|
background: #409eff;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-btn:hover {
|
||||||
|
background: #66b1ff;
|
||||||
|
border-color: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 为了防止内容被固定头部遮挡 */
|
||||||
|
.home {
|
||||||
|
padding-top: 72px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,276 @@
|
||||||
|
<template>
|
||||||
|
<div class="home-default">
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<main class="hero">
|
||||||
|
<div class="hero-overlay">
|
||||||
|
<img src="@/assets/examples/hero-bg.svg" class="hero-bg" alt="background" />
|
||||||
|
</div>
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1>专业的流程图设计工具</h1>
|
||||||
|
<p>简单易用的在线流程图绘制工具,帮助您快速创建流程图、思维导图、UML图等</p>
|
||||||
|
<router-link to="/files" class="btn btn-large">立即开始</router-link>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Examples Section -->
|
||||||
|
<section class="examples">
|
||||||
|
<div class="examples-content">
|
||||||
|
<h2>流程图案例展示</h2>
|
||||||
|
<p class="section-desc">适用于各种场景的流程图模板,帮助您快速开始</p>
|
||||||
|
|
||||||
|
<div class="example-grid">
|
||||||
|
<div class="example-card">
|
||||||
|
<div class="example-image">
|
||||||
|
<img src="@/assets/examples/business-process.svg" alt="业务流程图">
|
||||||
|
<div class="example-overlay">
|
||||||
|
<router-link to="/flow-edit" class="btn-try">立即尝试</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>业务流程图</h3>
|
||||||
|
<p>清晰展示业务流程,优化工作效率</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example-card">
|
||||||
|
<div class="example-image">
|
||||||
|
<img src="@/assets/examples/mind-map.svg" alt="思维导图">
|
||||||
|
<div class="example-overlay">
|
||||||
|
<router-link to="/flow-edit" class="btn-try">立即尝试</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>思维导图</h3>
|
||||||
|
<p>梳理思路结构,激发创意灵感</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example-card">
|
||||||
|
<div class="example-image">
|
||||||
|
<img src="@/assets/examples/uml.svg" alt="UML图">
|
||||||
|
<div class="example-overlay">
|
||||||
|
<router-link to="/flow-edit" class="btn-try">立即尝试</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>UML类图</h3>
|
||||||
|
<p>规范软件设计,提升开发效率</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example-card">
|
||||||
|
<div class="example-image">
|
||||||
|
<img src="@/assets/examples/org-chart.svg" alt="组织架构图">
|
||||||
|
<div class="example-overlay">
|
||||||
|
<router-link to="/flow-edit" class="btn-try">立即尝试</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>组织架构图</h3>
|
||||||
|
<p>直观展示组织结构,明确职责分工</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.home-default {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
margin-top: 64px;
|
||||||
|
min-height: 600px;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
/* 移除背景图片相关样式 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-content {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 24px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 22px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
margin-bottom: 40px;
|
||||||
|
line-height: 1.6;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-large {
|
||||||
|
padding: 16px 48px;
|
||||||
|
font-size: 18px;
|
||||||
|
background: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-large:hover {
|
||||||
|
background: transparent;
|
||||||
|
border-color: #fff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.examples {
|
||||||
|
padding: 80px 24px;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.examples-content {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.examples h2 {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-desc {
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-image {
|
||||||
|
position: relative;
|
||||||
|
aspect-ratio: 16/9;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-image img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card:hover .example-overlay {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card:hover .example-image img {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-try {
|
||||||
|
padding: 8px 24px;
|
||||||
|
background: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-try:hover {
|
||||||
|
background: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-card p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin: 0 16px 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.example-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.examples {
|
||||||
|
padding: 40px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-bg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,429 @@
|
||||||
|
<template>
|
||||||
|
<div class="login-container">
|
||||||
|
<!-- 左侧广告区域 -->
|
||||||
|
<div class="login-banner">
|
||||||
|
<div class="banner-content">
|
||||||
|
<h1>Flow Design</h1>
|
||||||
|
<p class="slogan">可视化流程设计工具</p>
|
||||||
|
<div class="features">
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">🎯</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>简单易用</h3>
|
||||||
|
<p>拖拽式设计,快速上手</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">🔄</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>实时协作</h3>
|
||||||
|
<p>多人在线,即时同步</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">📊</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>专业可靠</h3>
|
||||||
|
<p>企业级流程解决方案</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img src="@/assets/images/flow-banner.svg" alt="Flow Design Banner" class="banner-image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧登录区域 -->
|
||||||
|
<div class="login-content">
|
||||||
|
<div class="login-box">
|
||||||
|
<div class="login-header">
|
||||||
|
<img src="@/assets/logo.svg" alt="Flow Design" class="logo">
|
||||||
|
<h2>欢迎使用 Flow Design</h2>
|
||||||
|
<p class="subtitle">打造专业的流程设计工具</p>
|
||||||
|
</div>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
class="login-form"
|
||||||
|
>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input
|
||||||
|
v-model="form.username"
|
||||||
|
placeholder="用户名/邮箱"
|
||||||
|
:prefix-icon="User"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
v-model="form.password"
|
||||||
|
type="password"
|
||||||
|
placeholder="密码"
|
||||||
|
:prefix-icon="Lock"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<div class="form-options">
|
||||||
|
<el-checkbox v-model="form.rememberMe">记住我</el-checkbox>
|
||||||
|
<el-link type="primary" href="#" class="forgot-password">忘记密码?</el-link>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="login-button"
|
||||||
|
:loading="loading"
|
||||||
|
@click="submitForm(formRef)"
|
||||||
|
>
|
||||||
|
登 录
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="form-footer">
|
||||||
|
<span>还没有账号?</span>
|
||||||
|
<router-link to="/register" class="register-link">立即注册</router-link>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
import { User, Lock } from '@element-plus/icons-vue'
|
||||||
|
import { login } from '@/api/auth' // 导入 login 方法
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
rememberMe: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive<FormRules>({
|
||||||
|
username: [
|
||||||
|
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||||
|
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||||
|
{ min: 6, message: '密码长度不能小于6位', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const submitForm = (formEl: FormInstance | undefined): Promise<void> => {
|
||||||
|
if (!formEl) return Promise.reject('表单不存在')
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
formEl.validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
reject('表单验证失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
login({
|
||||||
|
username: form.username,
|
||||||
|
password: form.password,
|
||||||
|
rememberMe: form.rememberMe
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
localStorage.setItem('token', res.data.token)
|
||||||
|
ElMessage({
|
||||||
|
message: '登录成功!',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
router.push('/files')
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('登录失败:', error)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.login-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
min-width: 100vw;
|
||||||
|
display: flex;
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-banner {
|
||||||
|
width: 30%;
|
||||||
|
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||||
|
padding: 40px;
|
||||||
|
position: relative;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 100vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
max-width: 460px;
|
||||||
|
margin: auto 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slogan {
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-text h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-text p {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-image {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10%;
|
||||||
|
right: -10%;
|
||||||
|
width: 120%;
|
||||||
|
opacity: 0.1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
width: 400px;
|
||||||
|
max-width: 90%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header .logo {
|
||||||
|
height: 48px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header .subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-prefix {
|
||||||
|
position: absolute;
|
||||||
|
left: 12px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-user::before {
|
||||||
|
content: "👤";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-lock::before {
|
||||||
|
content: "🔒";
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 12px 12px 36px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
border-color: #409eff;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remember-me {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forgot-password {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
background: #409eff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button:hover {
|
||||||
|
background: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer {
|
||||||
|
margin-top: 24px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-link {
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-link:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.login-container {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-banner {
|
||||||
|
width: 100%;
|
||||||
|
height: 30vh;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-content {
|
||||||
|
height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
padding-left: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__prefix) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>价格</h2>
|
||||||
|
<p>这里是价格页面的内容。</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Pricing'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 添加页面特定的样式 */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,492 @@
|
||||||
|
<template>
|
||||||
|
<div class="register-container">
|
||||||
|
<!-- 左侧广告区域 -->
|
||||||
|
<div class="register-banner">
|
||||||
|
<div class="banner-content">
|
||||||
|
<h1>Flow Design</h1>
|
||||||
|
<p class="slogan">可视化流程设计工具</p>
|
||||||
|
<div class="features">
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">🎯</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>简单易用</h3>
|
||||||
|
<p>拖拽式设计,快速上手</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">🔄</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>实时协作</h3>
|
||||||
|
<p>多人在线,即时同步</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-item">
|
||||||
|
<i class="feature-icon">📊</i>
|
||||||
|
<div class="feature-text">
|
||||||
|
<h3>专业可靠</h3>
|
||||||
|
<p>企业级流程解决方案</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img src="@/assets/images/flow-banner.svg" alt="Flow Design Banner" class="banner-image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧注册区域 -->
|
||||||
|
<div class="register-content">
|
||||||
|
<div class="register-box">
|
||||||
|
<div class="register-header">
|
||||||
|
<img src="@/assets/logo.svg" alt="Flow Design" class="logo">
|
||||||
|
<h2>欢迎加入 Flow Design</h2>
|
||||||
|
<p class="subtitle">开启您的流程设计之旅</p>
|
||||||
|
</div>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
class="register-form"
|
||||||
|
>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input
|
||||||
|
v-model="form.username"
|
||||||
|
placeholder="用户名"
|
||||||
|
:prefix-icon="User"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="email">
|
||||||
|
<el-input
|
||||||
|
v-model="form.email"
|
||||||
|
placeholder="邮箱"
|
||||||
|
:prefix-icon="Message"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
v-model="form.password"
|
||||||
|
type="password"
|
||||||
|
placeholder="密码"
|
||||||
|
:prefix-icon="Lock"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="confirmPassword">
|
||||||
|
<el-input
|
||||||
|
v-model="form.confirmPassword"
|
||||||
|
type="password"
|
||||||
|
placeholder="确认密码"
|
||||||
|
:prefix-icon="Lock"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="agreeTerms">
|
||||||
|
<el-checkbox v-model="form.agreeTerms">
|
||||||
|
我已阅读并同意<el-link type="primary" href="#" class="terms-link">服务条款</el-link>
|
||||||
|
</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="register-button"
|
||||||
|
:loading="loading"
|
||||||
|
:disabled="!form.agreeTerms"
|
||||||
|
@click="submitForm(formRef)"
|
||||||
|
>
|
||||||
|
注 册
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="form-footer">
|
||||||
|
<span>已有账号?</span>
|
||||||
|
<router-link to="/login" class="login-link">立即登录</router-link>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import 'element-plus/es/components/message/style/css'
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
import { User, Message, Lock } from '@element-plus/icons-vue'
|
||||||
|
import { register } from '@/api/auth'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
username: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
agreeTerms: false
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const validatePass2 = (rule: any, value: any, callback: any) => {
|
||||||
|
if (value === '') {
|
||||||
|
callback(new Error('请再次输入密码'))
|
||||||
|
} else if (value !== form.password) {
|
||||||
|
callback(new Error('两次输入密码不一致!'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules = reactive<FormRules>({
|
||||||
|
username: [
|
||||||
|
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||||
|
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
|
||||||
|
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||||
|
{ min: 6, message: '密码长度不能小于6位', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
confirmPassword: [
|
||||||
|
{ required: true, message: '请再次输入密码', trigger: 'blur' },
|
||||||
|
{ validator: validatePass2, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
agreeTerms: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value) {
|
||||||
|
callback(new Error('请阅读并同意服务条款'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const submitForm = (formEl: FormInstance | undefined): Promise<void> => {
|
||||||
|
if (!formEl) return Promise.reject('表单不存在')
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
formEl.validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
reject('表单验证失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
register({
|
||||||
|
username: form.username,
|
||||||
|
email: form.email,
|
||||||
|
password: form.password
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '注册成功!正在跳转到登录页面...',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
router.push('/login')
|
||||||
|
}, 1500)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('注册失败:', error)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 复用登录页面的基础样式,只修改类名 */
|
||||||
|
.register-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
min-width: 100vw;
|
||||||
|
display: flex;
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-banner {
|
||||||
|
width: 30%;
|
||||||
|
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||||
|
padding: 40px;
|
||||||
|
position: relative;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 100vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
max-width: 460px;
|
||||||
|
margin: auto 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slogan {
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-text h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-text p {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-image {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10%;
|
||||||
|
right: -10%;
|
||||||
|
width: 120%;
|
||||||
|
opacity: 0.1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 其他样式保持与登录页一致,只需将 login 替换为 register */
|
||||||
|
.register-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-box {
|
||||||
|
width: 400px;
|
||||||
|
max-width: 90%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 复用其他样式并添加邮箱图标 */
|
||||||
|
.icon-email::before {
|
||||||
|
content: "📧";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 服务条款样式 */
|
||||||
|
.agree-terms {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terms-link {
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terms-link:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 禁用状态的注册按钮 */
|
||||||
|
.register-button:disabled {
|
||||||
|
background: #a0cfff;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.register-container {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-banner {
|
||||||
|
width: 100%;
|
||||||
|
height: 30vh;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-content {
|
||||||
|
height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-box {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加缺失的输入框样式 */
|
||||||
|
.form-item {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-prefix {
|
||||||
|
position: absolute;
|
||||||
|
left: 12px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-user::before {
|
||||||
|
content: "👤";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-lock::before {
|
||||||
|
content: "🔒";
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 12px 12px 36px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
border-color: #409eff;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注册按钮样式 */
|
||||||
|
.register-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
background: #409eff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-button:hover:not(:disabled) {
|
||||||
|
background: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注册框头部样式 */
|
||||||
|
.register-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-header .logo {
|
||||||
|
height: 48px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-header h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-header .subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer {
|
||||||
|
margin-top: 24px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-link {
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-link:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 修改表单相关样式 */
|
||||||
|
.register-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
padding-left: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__prefix) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 其他样式保持不变... */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<div class="community">
|
||||||
|
<div class="community-header">
|
||||||
|
<h2>社区作品</h2>
|
||||||
|
<div class="filter-options">
|
||||||
|
<select v-model="currentCategory">
|
||||||
|
<option value="all">全部分类</option>
|
||||||
|
<option value="business">商业图表</option>
|
||||||
|
<option value="tech">技术架构</option>
|
||||||
|
<option value="edu">教育培训</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="community-grid">
|
||||||
|
<div class="community-card" v-for="item in communityItems" :key="item.id">
|
||||||
|
<div class="work-preview">
|
||||||
|
<img :src="item.preview" :alt="item.title">
|
||||||
|
</div>
|
||||||
|
<div class="work-info">
|
||||||
|
<h3>{{ item.title }}</h3>
|
||||||
|
<div class="author-info">
|
||||||
|
<img :src="item.authorAvatar" :alt="item.author" class="avatar">
|
||||||
|
<span>{{ item.author }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="work-stats">
|
||||||
|
<span>👍 {{ item.likes }}</span>
|
||||||
|
<span>💬 {{ item.comments }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import businessProcess from '@/assets/examples/business-process.svg'
|
||||||
|
import defaultAvatar from '@/assets/avatars/default-avatar.svg'
|
||||||
|
|
||||||
|
const currentCategory = ref('all')
|
||||||
|
|
||||||
|
const communityItems = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '电商系统架构图',
|
||||||
|
preview: businessProcess,
|
||||||
|
author: '张三',
|
||||||
|
authorAvatar: defaultAvatar,
|
||||||
|
likes: 128,
|
||||||
|
comments: 32
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import '@/assets/styles/file-list.css';
|
||||||
|
|
||||||
|
.community-header {
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.community-card {
|
||||||
|
width: 280px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-preview img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-info {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<template>
|
||||||
|
<div class="favorites">
|
||||||
|
<h2>我的收藏</h2>
|
||||||
|
<!-- 内容 -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<template>
|
||||||
|
<div class="my-files">
|
||||||
|
<div class="file-list">
|
||||||
|
<div class="file-card" v-for="file in files" :key="file.id">
|
||||||
|
<div class="file-preview">
|
||||||
|
<img :src="file.preview" :alt="file.name">
|
||||||
|
</div>
|
||||||
|
<div class="file-info">
|
||||||
|
<h3>{{ file.name }}</h3>
|
||||||
|
<p>最后修改:{{ file.modifiedDate }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import businessProcess from '@/assets/examples/business-process.svg'
|
||||||
|
import mindMap from '@/assets/examples/mind-map.svg'
|
||||||
|
import umlDiagram from '@/assets/examples/uml.svg'
|
||||||
|
|
||||||
|
const files = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '业务流程图',
|
||||||
|
preview: businessProcess,
|
||||||
|
modifiedDate: '2024-01-20'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '思维导图',
|
||||||
|
preview: mindMap,
|
||||||
|
modifiedDate: '2024-01-18'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'UML类图',
|
||||||
|
preview: umlDiagram,
|
||||||
|
modifiedDate: '2024-01-15'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import '@/assets/styles/file-list.css';
|
||||||
|
|
||||||
|
.my-files {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<template>
|
||||||
|
<div class="recent">
|
||||||
|
<div class="file-list">
|
||||||
|
<div class="file-card" v-for="file in files" :key="file.id">
|
||||||
|
<div class="file-preview">
|
||||||
|
<img :src="file.preview" :alt="file.name">
|
||||||
|
</div>
|
||||||
|
<div class="file-info">
|
||||||
|
<h3>{{ file.name }}</h3>
|
||||||
|
<p>访问时间:{{ file.accessTime }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import businessProcess from '@/assets/examples/business-process.svg'
|
||||||
|
import mindMap from '@/assets/examples/mind-map.svg'
|
||||||
|
|
||||||
|
const files = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '项目流程图',
|
||||||
|
preview: businessProcess,
|
||||||
|
accessTime: '2024-03-15 14:30'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '系统架构图',
|
||||||
|
preview: mindMap,
|
||||||
|
accessTime: '2024-03-14 16:20'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.file-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 复用 FileManager.vue 中的卡片样式 */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="recommended">
|
||||||
|
<div class="template-categories">
|
||||||
|
<h3>热门模板</h3>
|
||||||
|
<div class="template-grid">
|
||||||
|
<div class="template-card" v-for="template in templates" :key="template.id">
|
||||||
|
<div class="template-preview">
|
||||||
|
<img :src="template.preview" :alt="template.name">
|
||||||
|
</div>
|
||||||
|
<div class="template-info">
|
||||||
|
<h4>{{ template.name }}</h4>
|
||||||
|
<p>{{ template.description }}</p>
|
||||||
|
<button class="btn-use">使用模板</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import businessProcess from '@/assets/examples/business-process.svg'
|
||||||
|
import orgChart from '@/assets/examples/org-chart.svg'
|
||||||
|
|
||||||
|
const templates = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '项目管理流程',
|
||||||
|
description: '适用于项目规划和任务管理',
|
||||||
|
preview: businessProcess
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '组织架构图',
|
||||||
|
description: '快速创建公司组织结构图',
|
||||||
|
preview: orgChart
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.template-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-card {
|
||||||
|
width: 280px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-preview img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-info {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-use {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<div class="trash">
|
||||||
|
<div class="trash-header">
|
||||||
|
<h2>回收站</h2>
|
||||||
|
<button class="btn-clear" @click="clearTrash">清空回收站</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="file-list">
|
||||||
|
<div class="file-card" v-for="file in deletedFiles" :key="file.id">
|
||||||
|
<div class="file-preview">
|
||||||
|
<img :src="file.preview" :alt="file.name">
|
||||||
|
</div>
|
||||||
|
<div class="file-info">
|
||||||
|
<h3>{{ file.name }}</h3>
|
||||||
|
<p>删除时间:{{ file.deleteTime }}</p>
|
||||||
|
<div class="file-actions">
|
||||||
|
<button class="btn-restore" @click="restoreFile(file.id)">还原</button>
|
||||||
|
<button class="btn-delete" @click="deleteFile(file.id)">删除</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import businessProcess from '@/assets/examples/business-process.svg'
|
||||||
|
|
||||||
|
const deletedFiles = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '旧版流程图',
|
||||||
|
preview: businessProcess,
|
||||||
|
deleteTime: '2024-03-10'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const restoreFile = (id: number) => {
|
||||||
|
// 还原文件逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteFile = (id: number) => {
|
||||||
|
// 永久删除文件逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearTrash = () => {
|
||||||
|
// 清空回收站逻辑
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import '@/assets/styles/file-list.css';
|
||||||
|
|
||||||
|
.trash-header {
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
margin-top: 12px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* 通用的文件列表横向布局样式 */
|
||||||
|
.file-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-card {
|
||||||
|
width: 280px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
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;
|
||||||
|
}
|
||||||