浏览代码

将组件库内容独立到edit.vue实现,方便统一网络请求

kagg886 1 月之前
父节点
当前提交
109d1bfefe

+ 10 - 32
src/components/assistant/ComponentLibrary.vue

@@ -1,41 +1,19 @@
 <script setup lang="ts">
-import { ref } from 'vue'
-import { Plus, Document } from '@element-plus/icons-vue'
+import { computed, ref } from 'vue'
+import { Plus } from '@element-plus/icons-vue'
 import Markdown from '/@/components/markdown/Markdown.vue'
 import type { ComponentLibraryItem, Content } from './types'
 
-const emit = defineEmits<{
-	addCard: [cardData: Content]
+const props = defineProps<{
+	library?: ComponentLibraryItem[]
 }>()
 
-// 组件库数据
-const componentLibrary = ref<ComponentLibraryItem[]>([
-	{
-		id: 'quote-block',
-		title: '引用块',
-		icon: Document,
-		description: '用于显示引用内容',
-		data: `> ### 重要提示
->
-> 这是一个引用块示例,可以用来显示重要信息、提示或者引用其他内容。
->
-> 支持多行内容和**格式化文本**。`,
-		preview: `> 这是一个引用块示例\n> 可以包含重要信息`
-	},
-	{
-		id: 'data-table',
-		title: '数据表格',
-		icon: 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 | 正常 |`
-	}
-])
+const componentLibrary = computed(() => props.library || [])
+
+const emit = defineEmits<{
+	// eslint-disable-next-line no-unused-vars
+	(e: 'addCard', cardData: Content): void
+}>()
 
 // 拖拽开始
 const handleDragStart = (event: DragEvent, component: any) => {

+ 13 - 8
src/components/assistant/DashboardDesigner.vue

@@ -1,19 +1,24 @@
 <script setup lang="ts">
-import { ref, computed, nextTick } from 'vue'
+import { ref } from 'vue'
 import DraggableCard from './DraggableCard.vue'
-import { Delete, Document } from '@element-plus/icons-vue'
+import { Document } from '@element-plus/icons-vue'
 import type { MarkdownDashBoard, Position, Size, Content, AddCardData } from './types'
 
-const props = defineProps<{
+defineProps<{
 	cards: MarkdownDashBoard[]
 }>()
 
 const emit = defineEmits<{
-	updatePosition: [id: string, position: Position]
-	updateSize: [id: string, size: Size]
-	updateContent: [id: string, content: Content]
-	removeCard: [id: string]
-	addCard: [cardData: AddCardData]
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updatePosition', id: string, position: Position): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updateSize', id: string, size: Size): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updateContent', id: string, content: Content): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'removeCard', id: string): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'addCard', cardData: AddCardData): void
 }>()
 
 const designerContainer = ref<HTMLElement>()

+ 8 - 4
src/components/assistant/DraggableCard.vue

@@ -9,10 +9,14 @@ const props = defineProps<{
 }>()
 
 const emit = defineEmits<{
-	updatePosition: [id: string, position: Position]
-	updateSize: [id: string, size: Size]
-	updateContent: [id: string, content: Content]
-	remove: [id: string]
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updatePosition', id: string, position: Position): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updateSize', id: string, size: Size): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'updateContent', id: string, content: Content): void
+	// eslint-disable-next-line no-unused-vars
+	(e: 'remove', id: string): void
 }>()
 
 const cardRef = ref<HTMLElement>()

+ 55 - 47
src/views/assistant/dashboard/edit.vue

@@ -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>