|
@@ -1,11 +1,148 @@
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
|
+import { ref, onMounted, computed } from 'vue'
|
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
|
+import { Download, Grid, TrendCharts, BarChart } from '@element-plus/icons-vue'
|
|
|
|
+import assist from '/@/api/assist'
|
|
|
|
+import { useLoading } from '/@/utils/loading-util'
|
|
|
|
+import VueCharts from './VueCharts.vue'
|
|
|
|
+import download from 'downloadjs'
|
|
|
|
+
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
uuid: string
|
|
uuid: string
|
|
}>()
|
|
}>()
|
|
|
|
+
|
|
|
|
+// 定义数据结构类型
|
|
|
|
+interface StructData {
|
|
|
|
+ fields: string[]
|
|
|
|
+ data: { [key: string]: string }[]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const data = ref<StructData>()
|
|
|
|
+
|
|
|
|
+const { loading: loadingStruct, doLoading: doLoadingStruct } = useLoading(async () => {
|
|
|
|
+ data.value = await assist.struct(props.uuid)
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 导出数据为CSV格式
|
|
|
|
+const exportToCSV = () => {
|
|
|
|
+ if (!data.value || !data.value.fields || !data.value.data) {
|
|
|
|
+ ElMessage.warning('暂无数据可导出')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 构建CSV内容
|
|
|
|
+ const headers = data.value.fields.map((it) => `"${it}"`).join(',')
|
|
|
|
+ const rows = data.value.data.map(rowJson => {
|
|
|
|
+ return data.value!.fields.map(field => `"${rowJson[field]}"`).join(',')
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const csvContent = [headers, ...rows].join('\n')
|
|
|
|
+
|
|
|
|
+ download(csvContent, 'export.csv', 'text/csv,charset=utf-8;')
|
|
|
|
+
|
|
|
|
+ ElMessage.success('数据导出成功')
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('导出失败:', error)
|
|
|
|
+ ElMessage.error('导出失败,请重试')
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 组件挂载时加载数据
|
|
|
|
+onMounted(doLoadingStruct)
|
|
|
|
+
|
|
|
|
+const display = ref<'table' | 'bar' | 'line'>('table')
|
|
|
|
+
|
|
|
|
+const barChart = ref()
|
|
|
|
+const lineChart = ref()
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<template>
|
|
- <div>{{props.uuid}}</div>
|
|
|
|
|
|
+ <div class="struct-data-container">
|
|
|
|
+ <el-card v-loading="loadingStruct" shadow="none" :body-style="{ padding: 0, margin: 0 }">
|
|
|
|
+ <template #header>
|
|
|
|
+ <div class="card-header">
|
|
|
|
+ <span>结构化数据表格</span>
|
|
|
|
+ <el-popover placement="top" :width="120" trigger="hover" content="导出为CSV文件">
|
|
|
|
+ <template #reference>
|
|
|
|
+ <el-button
|
|
|
|
+ :icon="Download"
|
|
|
|
+ size="small"
|
|
|
|
+ text
|
|
|
|
+ circle
|
|
|
|
+ @click="exportToCSV"
|
|
|
|
+ :disabled="!data || !data.fields || !data.data || data.data.length === 0"
|
|
|
|
+ class="export-btn"
|
|
|
|
+ />
|
|
|
|
+ </template>
|
|
|
|
+ </el-popover>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <!-- 表格内容 -->
|
|
|
|
+ <div v-if="data && data.fields && data.data" class="table-wrapper">
|
|
|
|
+ <el-table :data="data.data" stripe border size="small" max-height="400">
|
|
|
|
+ <el-table-column v-for="field in data.fields" :key="field" :prop="field" :label="field" align="center" min-width="120">
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
+ <span>{{ row[field] || '-' }}</span>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 空数据状态 -->
|
|
|
|
+ <div v-else-if="!loadingStruct" class="empty-state">
|
|
|
|
+ <el-empty description="暂无数据" />
|
|
|
|
+ </div>
|
|
|
|
+ </el-card>
|
|
|
|
+ </div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
-<style scoped lang="scss"></style>
|
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.struct-data-container {
|
|
|
|
+ margin: 16px 0;
|
|
|
|
+
|
|
|
|
+ .card-header {
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ align-items: center;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
|
+
|
|
|
|
+ .export-btn {
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ background-color: var(--el-color-primary-light-9);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &:disabled {
|
|
|
|
+ color: var(--el-text-color-disabled);
|
|
|
|
+ cursor: not-allowed;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .table-wrapper {
|
|
|
|
+ .el-table {
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .empty-state {
|
|
|
|
+ padding: 40px 0;
|
|
|
|
+ text-align: center;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ :deep(table) {
|
|
|
|
+ margin: 0 !important;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.el-card {
|
|
|
|
+ background: transparent !important;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+:deep(.el-table__cell) {
|
|
|
|
+ background: transparent !important;
|
|
|
|
+}
|
|
|
|
+</style>
|