重写复现方法
This commit is contained in:
@@ -1,51 +1,649 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:open="visible"
|
||||
title="数据源详情"
|
||||
title="表详情"
|
||||
:width="modalWidth"
|
||||
:centered="true"
|
||||
:body-style="bodyStyle"
|
||||
:footer="null"
|
||||
@cancel="$emit('close')"
|
||||
>
|
||||
<div class="name-detail-content">
|
||||
<div class="detail-header">
|
||||
<h3 style="margin: 0;">{{ taskName }} {{ taskId }} 详情</h3>
|
||||
<div class="table-detail-container">
|
||||
<!-- 左侧表基础信息区域 -->
|
||||
<div class="left-section">
|
||||
<h3 class="section-title">表基础信息</h3>
|
||||
|
||||
<!-- 基础信息卡片容器 -->
|
||||
<a-card class="info-card basic-info-card">
|
||||
<div class="basic-info-item">
|
||||
<span class="label">数据库:</span>
|
||||
<span class="value">{{ tableBasicInfo.database }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">表名称:</span>
|
||||
<span class="value">{{ tableBasicInfo.tableName }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">表描述:</span>
|
||||
<span class="value">{{ tableBasicInfo.tableDesc }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">创建时间:</span>
|
||||
<span class="value">{{ tableBasicInfo.createTime }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">更新时间:</span>
|
||||
<span class="value">{{ tableBasicInfo.updateTime }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">数据类型:</span>
|
||||
<span class="value">{{ tableBasicInfo.dataType }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">更新频率:</span>
|
||||
<span class="value">{{ tableBasicInfo.updateFreq }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">字段数量:</span>
|
||||
<span class="value">{{ tableBasicInfo.fieldCount }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">访问权限:</span>
|
||||
<span class="value">{{ tableBasicInfo.accessRights }}</span>
|
||||
</div>
|
||||
<div class="basic-info-item">
|
||||
<span class="label">备注:</span>
|
||||
<span class="value">{{ tableBasicInfo.remark }}</span>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<!-- 存储量卡片容器 -->
|
||||
<a-card class="info-card storage-card">
|
||||
<div class="storage-info">
|
||||
<span class="storage-label">存储量:</span>
|
||||
<span class="storage-value">{{ tableBasicInfo.storageCount }}</span>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
<div class="detail-list">
|
||||
<div class="detail-item"><span class="label">数据源名称:</span><span class="value">{{ taskName }}</span></div>
|
||||
<div class="detail-item"><span class="label">数据类型:</span><span class="value">结构化数据表(MySQL)</span></div>
|
||||
<div class="detail-item"><span class="label">数据更新频率:</span><span class="value">每日增量更新</span></div>
|
||||
<div class="detail-item"><span class="label">字段数量:</span><span class="value">28个(含主键、时间戳、业务字段)</span></div>
|
||||
<div class="detail-item"><span class="label">访问权限:</span><span class="value">需申请(审批后只读访问)</span></div>
|
||||
<div class="detail-item"><span class="label">备注:</span><span class="value">该表包含核心业务数据,禁止用于非授权场景。</span></div>
|
||||
|
||||
<!-- 右侧标签页内容区域 -->
|
||||
<div class="right-section">
|
||||
<a-tabs
|
||||
default-active-key="fieldInfo"
|
||||
@change="handleTabChange"
|
||||
class="google-style-tabs"
|
||||
>
|
||||
<a-tab-pane tab="字段信息" key="fieldInfo">
|
||||
<div class="tab-content">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="fieldData"
|
||||
bordered
|
||||
:pagination="false"
|
||||
:scroll="{ y: 'calc(100% - 20px)' }"
|
||||
class="fixed-header-table"
|
||||
/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="生成SELECT" key="generateSelect">
|
||||
<div class="tab-content sql-content">
|
||||
<div class="sql-header">
|
||||
<span>SELECT 语句</span>
|
||||
<a-button
|
||||
type="text"
|
||||
icon="copy"
|
||||
@click="copyToClipboard(selectSql)"
|
||||
class="copy-btn"
|
||||
>
|
||||
复制
|
||||
</a-button>
|
||||
</div>
|
||||
<pre>{{ selectSql }}</pre>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="生成DDL" key="generateDDL">
|
||||
<div class="tab-content sql-content">
|
||||
<div class="sql-header">
|
||||
<span>DDL 语句</span>
|
||||
<a-button
|
||||
type="text"
|
||||
icon="copy"
|
||||
@click="copyToClipboard(ddlSql)"
|
||||
class="copy-btn"
|
||||
>
|
||||
复制
|
||||
</a-button>
|
||||
</div>
|
||||
<pre>{{ ddlSql }}</pre>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, defineProps, defineEmits } from 'vue';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
import { computed, defineProps, defineEmits, ref } from 'vue';
|
||||
import { Modal, Tabs, Table, Card, Button, message } from 'ant-design-vue';
|
||||
import { CopyOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
// 定义组件属性
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
taskName: string;
|
||||
taskId: string ;
|
||||
taskName?: string;
|
||||
taskId?: string;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const modalWidth = computed(() => window.innerWidth * 0.6);
|
||||
// 定义组件事件
|
||||
const emit = defineEmits(['close', 'tabChange']);
|
||||
|
||||
// 处理标签页切换
|
||||
const handleTabChange = (key: string) => {
|
||||
emit('tabChange', key);
|
||||
};
|
||||
|
||||
// 复制到剪贴板功能
|
||||
const copyToClipboard = (text: string) => {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
message.success('复制成功');
|
||||
}).catch(() => {
|
||||
message.error('复制失败,请手动复制');
|
||||
});
|
||||
};
|
||||
|
||||
// 表基础信息数据
|
||||
const tableBasicInfo = ref({
|
||||
database: 'work',
|
||||
tableName: 'biz_cities',
|
||||
tableDesc: '市区信息表',
|
||||
storageCount: '333条',
|
||||
createTime: '2025-08-29 15:54:41',
|
||||
updateTime: '2025-08-29 15:54:41',
|
||||
dataType: '结构化数据表(MySQL)',
|
||||
updateFreq: '每日增量更新',
|
||||
fieldCount: '13个(含主键、时间戳、业务字段)',
|
||||
accessRights: '需申请(审批后只读访问)',
|
||||
remark: '该表包含核心业务数据,禁止用于非授权场景。'
|
||||
});
|
||||
|
||||
// 字段信息表格列定义
|
||||
const columns = ref([
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 80,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '字段名称',
|
||||
dataIndex: 'fieldName',
|
||||
key: 'fieldName',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '字段类型',
|
||||
dataIndex: 'fieldType',
|
||||
key: 'fieldType',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '是否主键',
|
||||
dataIndex: 'isPrimary',
|
||||
key: 'isPrimary',
|
||||
width: 120,
|
||||
align: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
// 字段信息表格数据
|
||||
const fieldData = ref([
|
||||
{
|
||||
key: '1',
|
||||
index: '1',
|
||||
fieldName: 'id',
|
||||
fieldType: 'datetime',
|
||||
description: '主键',
|
||||
isPrimary: 'PRI'
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
index: '2',
|
||||
fieldName: 'create_time',
|
||||
fieldType: 'varchar',
|
||||
description: '记录时间',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
index: '3',
|
||||
fieldName: 'province_code',
|
||||
fieldType: 'varchar',
|
||||
description: '省份编码',
|
||||
isPrimary: 'MUL'
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
index: '4',
|
||||
fieldName: 'city_code',
|
||||
fieldType: 'varchar',
|
||||
description: '市区编码',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
index: '5',
|
||||
fieldName: 'city_name',
|
||||
fieldType: 'varchar',
|
||||
description: '市区名称',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
index: '6',
|
||||
fieldName: 'area_code',
|
||||
fieldType: 'varchar',
|
||||
description: '市区区号',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
index: '7',
|
||||
fieldName: 'area_type',
|
||||
fieldType: 'varchar',
|
||||
description: '市区级别',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
index: '8',
|
||||
fieldName: 'update_time',
|
||||
fieldType: 'varchar',
|
||||
description: '更新时间',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
index: '9',
|
||||
fieldName: 'data_status',
|
||||
fieldType: 'varchar',
|
||||
description: '数据状态',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '10',
|
||||
index: '10',
|
||||
fieldName: 'f_tenant_id',
|
||||
fieldType: 'varchar',
|
||||
description: '租户id',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '11',
|
||||
index: '11',
|
||||
fieldName: 'f_flow_id',
|
||||
fieldType: 'datetime',
|
||||
description: '流程id',
|
||||
isPrimary: 'MUL'
|
||||
},
|
||||
{
|
||||
key: '12',
|
||||
index: '12',
|
||||
fieldName: 'f_flow_task_id',
|
||||
fieldType: 'datetime',
|
||||
description: '流程任务主键',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '13',
|
||||
index: '13',
|
||||
fieldName: 'f_flow_state',
|
||||
fieldType: 'bigint',
|
||||
description: '流程任务状态',
|
||||
isPrimary: ''
|
||||
},
|
||||
// 添加更多数据用于测试滚动效果
|
||||
{
|
||||
key: '14',
|
||||
index: '14',
|
||||
fieldName: 'test_field1',
|
||||
fieldType: 'varchar',
|
||||
description: '测试字段1',
|
||||
isPrimary: ''
|
||||
},
|
||||
{
|
||||
key: '15',
|
||||
index: '15',
|
||||
fieldName: 'test_field2',
|
||||
fieldType: 'int',
|
||||
description: '测试字段2',
|
||||
isPrimary: ''
|
||||
}
|
||||
]);
|
||||
|
||||
// SELECT语句
|
||||
const selectSql = ref(`SELECT
|
||||
id,
|
||||
create_time,
|
||||
province_code,
|
||||
city_code,
|
||||
city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,
|
||||
data_status,
|
||||
city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,
|
||||
city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,city_name,
|
||||
area_code,
|
||||
area_type,
|
||||
update_time,
|
||||
f_tenant_id,
|
||||
f_flow_id,
|
||||
f_flow_task_id,
|
||||
f_flow_state
|
||||
FROM
|
||||
biz_cities;`);
|
||||
|
||||
// DDL语句
|
||||
const ddlSql = ref(`CREATE TABLE \`biz_cities\` (
|
||||
\`id\` datetime NOT NULL COMMENT '主键',
|
||||
\`create_time\` varchar COMMENT '记录时间',
|
||||
\`province_code\` varchar COMMENT '省份编码',
|
||||
\`city_code\` varchar COMMENT '市区编码',
|
||||
\`city_name\` varchar COMMENT '市区名称',
|
||||
\`area_code\` varchar COMMENT '市区区号',
|
||||
\`area_type\` varchar COMMENT '市区级别',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`update_time\` varchar COMMENT '更新时间',
|
||||
\`data_status\` varchar COMMENT '数据状态',
|
||||
\`f_tenant_id\` varchar COMMENT '租户id',
|
||||
\`f_flow_id\` datetime COMMENT '流程id',
|
||||
\`f_flow_task_id\` datetime COMMENT '流程任务主键',
|
||||
\`f_flow_state\` bigint COMMENT '流程任务状态',
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_province_code\` (\`province_code\`),
|
||||
KEY \`idx_f_flow_id\` (\`f_flow_id\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='市区信息表';`);
|
||||
|
||||
// 计算模态框宽度
|
||||
const modalWidth = computed(() => {
|
||||
return Math.min(window.innerWidth * 0.9, 1400);
|
||||
});
|
||||
|
||||
// 计算模态框内容区域样式
|
||||
const bodyStyle = computed(() => ({
|
||||
height: `${window.innerHeight * 0.6}px`,
|
||||
overflowY: 'auto'
|
||||
height: `${Math.min(window.innerHeight * 0.8, 800)}px`,
|
||||
overflowY: 'hidden',
|
||||
padding: '16px 24px'
|
||||
}));
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.name-detail-content .detail-header { margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #f0f0f0; }
|
||||
.name-detail-content .detail-list .detail-item { margin-bottom: 12px; display: flex; align-items: flex-start; }
|
||||
.name-detail-content .detail-list .detail-item .label { color: #666; font-weight: 500; width: 120px; flex-shrink: 0; }
|
||||
.name-detail-content .detail-list .detail-item .value { color: #333; flex-grow: 1; }
|
||||
</style>
|
||||
.table-detail-container {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.left-section {
|
||||
width: 320px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
overflow-y: auto;
|
||||
max-height: 100%;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.right-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2329;
|
||||
margin: 0 0 8px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
// 卡片样式
|
||||
.info-card {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #e0e0e0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.basic-info-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.storage-card {
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.storage-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storage-label {
|
||||
color: #6b7280;
|
||||
font-weight: 500;
|
||||
width: 90px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.storage-value {
|
||||
color: #1a73e8;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.basic-info-item {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.basic-info-item .label {
|
||||
color: #6b7280;
|
||||
font-weight: 500;
|
||||
width: 90px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.basic-info-item .value {
|
||||
color: #1f2329;
|
||||
flex-grow: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
// 谷歌风格标签页
|
||||
.google-style-tabs {
|
||||
--active-tab-color: #e8f0fe;
|
||||
--active-text-color: #1967d2;
|
||||
|
||||
.ant-tabs-nav {
|
||||
margin: 0;
|
||||
padding-left: 16px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.ant-tabs-tab {
|
||||
padding: 12px 24px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #5f6368;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: #1967d2;
|
||||
background-color: rgba(25, 103, 210, 0.04);
|
||||
}
|
||||
|
||||
&.ant-tabs-tab-active {
|
||||
color: var(--active-text-color);
|
||||
background-color: var(--active-tab-color);
|
||||
border-bottom: 2px solid var(--active-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-ink-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-tabs-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
// SQL内容样式
|
||||
.sql-content {
|
||||
background-color: #f9fafb;
|
||||
border-radius: 6px;
|
||||
padding: 0;
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sql-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
background-color: #f1f3f4;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
color: #1967d2;
|
||||
padding: 4px 8px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(25, 103, 210, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
padding: 16px;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
// 表格样式
|
||||
.fixed-header-table {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
background-color: #f8fafc;
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ant-table-tbody {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条样式优化
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user