|
@@ -1,47 +1,28 @@
|
|
|
<script setup lang="ts">
|
|
|
import { useLoading } from '/@/utils/loading-util'
|
|
|
-import { computed, ref } from 'vue'
|
|
|
+import { computed, onMounted, ref } from 'vue'
|
|
|
import DashboardDesigner from '/@/components/assistant/DashboardDesigner.vue'
|
|
|
import ComponentLibrary from '/@/components/assistant/ComponentLibrary.vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
-import type { MarkdownDashBoard, Position, Size, Content, AddCardData } from '/@/components/assistant/types'
|
|
|
+import type { MarkdownDashBoard, Position, Size, Content, AddCardData, ComponentLibraryItem } from '/@/components/assistant/types'
|
|
|
|
|
|
// 预留props,暂时不使用
|
|
|
-// const props = defineProps<{
|
|
|
-// id?: number
|
|
|
-// }>()
|
|
|
+const props = defineProps<{
|
|
|
+ id?: number
|
|
|
+}>()
|
|
|
|
|
|
-const data = ref<MarkdownDashBoard[]>([
|
|
|
- // 示例数据
|
|
|
- {
|
|
|
- id: 'card-1',
|
|
|
- x: 10,
|
|
|
- y: 10,
|
|
|
- w: 40,
|
|
|
- h: 30,
|
|
|
- z: 1,
|
|
|
- title: '示例卡片1',
|
|
|
- data: '> 这是一个引用块示例\n> \n> 可以包含多行内容'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'card-2',
|
|
|
- x: 55,
|
|
|
- y: 15,
|
|
|
- w: 35,
|
|
|
- h: 25,
|
|
|
- z: 2,
|
|
|
- title: '示例卡片2',
|
|
|
- data: '| 列1 | 列2 | 列3 |\n|-----|-----|-----|\n| 数据1 | 数据2 | 数据3 |\n| 数据4 | 数据5 | 数据6 |'
|
|
|
- }
|
|
|
-])
|
|
|
+const data = ref<MarkdownDashBoard[]>([])
|
|
|
|
|
|
// 预留加载功能,暂时不使用
|
|
|
-// const { loading: loadingDashboard, doLoading: doLoadingDashBoard } = useLoading(async () => {
|
|
|
-// if (props.id === undefined) {
|
|
|
-// return
|
|
|
-// }
|
|
|
-// //TODO fetch remote
|
|
|
-// })
|
|
|
+const { loading: loadingDashboard, doLoading: doLoadingDashBoard } = useLoading(async () => {
|
|
|
+ if (props.id === undefined) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
|
+ //TODO fetch remote
|
|
|
+})
|
|
|
+
|
|
|
+onMounted(doLoadingDashBoard)
|
|
|
|
|
|
const renderer = computed<MarkdownDashBoard[]>(() => [...data.value].sort((a, b) => a.z - b.z))
|
|
|
|
|
@@ -52,6 +33,7 @@ const generateId = () => {
|
|
|
|
|
|
const { loading: loadingDashboardSubmit, doLoading: doLoadingDashboardSubmit } = useLoading(async () => {
|
|
|
try {
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
|
// TODO: 实际的保存逻辑
|
|
|
// 这里应该调用API保存data.value到后端
|
|
|
ElMessage.success('仪表板保存成功')
|
|
@@ -69,16 +51,16 @@ const addCard = (cardData: AddCardData) => {
|
|
|
y: cardData.y ?? Math.random() * 50,
|
|
|
w: 30,
|
|
|
h: 25,
|
|
|
- z: Math.max(...data.value.map(item => item.z), 0) + 1,
|
|
|
+ z: Math.max(...data.value.map((item) => item.z), 0) + 1,
|
|
|
title: cardData.title,
|
|
|
- data: cardData.data
|
|
|
+ data: cardData.data,
|
|
|
}
|
|
|
data.value.push(newCard)
|
|
|
}
|
|
|
|
|
|
// 更新卡片位置
|
|
|
const updateCardPosition = (id: string, position: Position) => {
|
|
|
- const card = data.value.find(item => item.id === id)
|
|
|
+ const card = data.value.find((item) => item.id === id)
|
|
|
if (card) {
|
|
|
card.x = position.x
|
|
|
card.y = position.y
|
|
@@ -87,7 +69,7 @@ const updateCardPosition = (id: string, position: Position) => {
|
|
|
|
|
|
// 更新卡片大小
|
|
|
const updateCardSize = (id: string, size: Size) => {
|
|
|
- const card = data.value.find(item => item.id === id)
|
|
|
+ const card = data.value.find((item) => item.id === id)
|
|
|
if (card) {
|
|
|
card.w = size.w
|
|
|
card.h = size.h
|
|
@@ -96,7 +78,7 @@ const updateCardSize = (id: string, size: Size) => {
|
|
|
|
|
|
// 更新卡片内容
|
|
|
const updateCardContent = (id: string, content: Content) => {
|
|
|
- const card = data.value.find(item => item.id === id)
|
|
|
+ const card = data.value.find((item) => item.id === id)
|
|
|
if (card) {
|
|
|
card.title = content.title
|
|
|
card.data = content.data
|
|
@@ -105,11 +87,41 @@ const updateCardContent = (id: string, content: Content) => {
|
|
|
|
|
|
// 删除卡片
|
|
|
const removeCard = (id: string) => {
|
|
|
- const index = data.value.findIndex(item => item.id === id)
|
|
|
+ const index = data.value.findIndex((item) => item.id === id)
|
|
|
if (index !== -1) {
|
|
|
data.value.splice(index, 1)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// 组件库数据
|
|
|
+const library = ref<ComponentLibraryItem[]>([
|
|
|
+ {
|
|
|
+ id: 'quote-block',
|
|
|
+ title: '引用块',
|
|
|
+ icon: 'ele-Document',
|
|
|
+ description: '用于显示引用内容',
|
|
|
+ data: `> ### 重要提示
|
|
|
+>
|
|
|
+> 这是一个引用块示例,可以用来显示重要信息、提示或者引用其他内容。
|
|
|
+>
|
|
|
+> 支持多行内容和**格式化文本**。`,
|
|
|
+ preview: `> 这是一个引用块示例\n> 可以包含重要信息`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 'data-table',
|
|
|
+ title: '数据表格',
|
|
|
+ icon: 'ele-Document',
|
|
|
+ description: '用于显示结构化数据',
|
|
|
+ data: `| 指标名称 | 当前值 | 目标值 | 完成率 |
|
|
|
+|----------|--------|--------|--------|
|
|
|
+| 用户注册 | 1,234 | 1,500 | 82.3% |
|
|
|
+| 活跃用户 | 856 | 1,000 | 85.6% |
|
|
|
+| 转化率 | 12.5% | 15% | 83.3% |
|
|
|
+| 收入 | ¥45,678 | ¥50,000 | 91.4% |`,
|
|
|
+ preview: `| 指标 | 数值 | 状态 |\n|------|------|------|\n| 用户 | 1,234 | 正常 |`,
|
|
|
+ },
|
|
|
+])
|
|
|
+//
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -120,18 +132,14 @@ const removeCard = (id: string) => {
|
|
|
<h2>仪表板设计器</h2>
|
|
|
</div>
|
|
|
<div class="toolbar-right">
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- @click="doLoadingDashboardSubmit"
|
|
|
- :loading="loadingDashboardSubmit"
|
|
|
- >
|
|
|
+ <el-button type="primary" @click="doLoadingDashboardSubmit" :loading="loadingDashboardSubmit" :disabled="loadingDashboard">
|
|
|
保存仪表板
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 主要内容区域 -->
|
|
|
- <div class="main-content">
|
|
|
+ <div class="main-content" v-loading="loadingDashboard">
|
|
|
<!-- 左侧设计器面板 -->
|
|
|
<div class="designer-panel">
|
|
|
<DashboardDesigner
|
|
@@ -146,7 +154,7 @@ const removeCard = (id: string) => {
|
|
|
|
|
|
<!-- 右侧组件库面板 -->
|
|
|
<div class="library-panel">
|
|
|
- <ComponentLibrary @add-card="addCard" />
|
|
|
+ <ComponentLibrary :library="library" @add-card="addCard" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|