生成历史
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
This commit is contained in:
@@ -24,6 +24,13 @@ const prefix = 'code/';
|
||||
// return requestClient.get<any>(`${prefix}detail`, { params: { id } });
|
||||
// }
|
||||
|
||||
/**
|
||||
* 代码生成记录
|
||||
* @param data
|
||||
*/
|
||||
export async function getCodeGenerationListApi(data: Record<string, any> = {}) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
/**
|
||||
* 代码生成
|
||||
* @param data
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent, ref } from 'vue';
|
||||
import { defineAsyncComponent, onMounted, ref } from 'vue';
|
||||
|
||||
import { confirm, Page } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { Button, Drawer, Empty, List, message, Modal, Tag } from 'ant-design-vue';
|
||||
|
||||
import { JsonViewer } from '@vben/common-ui';
|
||||
|
||||
import { downloadByData } from '#/util/tool';
|
||||
import {
|
||||
codeGenerationDownloadApi,
|
||||
generationApi,
|
||||
getCodeGenerationListApi,
|
||||
} from '#/views/code-generation/api';
|
||||
|
||||
import type { CodeGenData } from './utils/data-transformer';
|
||||
@@ -19,6 +22,25 @@ import JsonImport from './components/json-import.vue';
|
||||
import ManualForm from './components/manual-form.vue';
|
||||
import ModeSelector from './components/mode-selector.vue';
|
||||
|
||||
// 生成历史相关
|
||||
interface GenerationHistory {
|
||||
id: number;
|
||||
title: string;
|
||||
file_name: string;
|
||||
path: string;
|
||||
params: any; // JSON对象
|
||||
created_at: string; // 已格式化的时间字符串
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
const historyDrawerVisible = ref(false);
|
||||
const historyList = ref<GenerationHistory[]>([]);
|
||||
const historyLoading = ref(false);
|
||||
|
||||
// JSON详情查看
|
||||
const jsonViewerVisible = ref(false);
|
||||
const currentJsonData = ref<any>(null);
|
||||
|
||||
// 懒加载组件
|
||||
const ModeSelectorComponent = defineAsyncComponent(() =>
|
||||
Promise.resolve(ModeSelector),
|
||||
@@ -72,10 +94,57 @@ const handleGenerate = async (data: CodeGenData) => {
|
||||
downloadByData(blob, res.file_name, 'application/zip');
|
||||
});
|
||||
});
|
||||
// 生成成功后刷新历史记录
|
||||
if (historyDrawerVisible.value) {
|
||||
loadHistoryList();
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '代码生成失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 加载生成历史列表
|
||||
const loadHistoryList = async () => {
|
||||
historyLoading.value = true;
|
||||
try {
|
||||
getCodeGenerationListApi({}).then((res) => {
|
||||
historyList.value = res.items;
|
||||
});
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '加载历史记录失败');
|
||||
historyList.value = [];
|
||||
} finally {
|
||||
historyLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 打开历史记录抽屉
|
||||
const handleOpenHistory = () => {
|
||||
historyDrawerVisible.value = true;
|
||||
loadHistoryList();
|
||||
};
|
||||
|
||||
// 下载历史记录
|
||||
const handleDownloadHistory = async (item: GenerationHistory) => {
|
||||
try {
|
||||
|
||||
// return console.log(item);
|
||||
codeGenerationDownloadApi(item.id).then((blob) => {
|
||||
downloadByData(blob, item.file_name, 'application/zip');
|
||||
message.success('下载成功');
|
||||
});
|
||||
// const blob = await codeGenerationDownloadApi(item.id);
|
||||
// downloadByData(blob, item.file_name, 'application/zip');
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '下载失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 查看JSON详情
|
||||
const handleViewJson = (item: GenerationHistory) => {
|
||||
currentJsonData.value = item.params;
|
||||
jsonViewerVisible.value = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -83,6 +152,15 @@ const handleGenerate = async (data: CodeGenData) => {
|
||||
:title="currentMode ? modeTitles[currentMode] : '代码生成器'"
|
||||
auto-content-height
|
||||
>
|
||||
<template #extra>
|
||||
<Button
|
||||
v-if="!currentMode"
|
||||
type="primary"
|
||||
@click="handleOpenHistory"
|
||||
>
|
||||
<i class="fa-solid fa-clock-rotate-left mr-2"></i>生成历史
|
||||
</Button>
|
||||
</template>
|
||||
<Transition name="fade-slide" mode="out-in">
|
||||
<!-- 模式选择界面 -->
|
||||
<div v-if="!currentMode" key="selector" class="mode-selector-container">
|
||||
@@ -131,6 +209,123 @@ const handleGenerate = async (data: CodeGenData) => {
|
||||
@back="handleBack"
|
||||
/>
|
||||
</Transition>
|
||||
|
||||
<!-- 生成历史抽屉 -->
|
||||
<Drawer
|
||||
v-model:open="historyDrawerVisible"
|
||||
title="生成历史"
|
||||
:width="700"
|
||||
placement="right"
|
||||
class="history-drawer"
|
||||
>
|
||||
<div v-if="historyLoading" class="flex h-64 items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fa-solid fa-spinner fa-spin text-2xl text-primary mb-2"></i>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="historyList.length === 0" class="flex h-64 items-center justify-center">
|
||||
<Empty description="暂无生成记录" />
|
||||
</div>
|
||||
<div v-else class="history-list-clean">
|
||||
<div
|
||||
v-for="item in historyList"
|
||||
:key="item.id"
|
||||
class="history-item-clean"
|
||||
>
|
||||
<div class="history-item-wrapper">
|
||||
<!-- 左侧内容 -->
|
||||
<div class="history-item-left">
|
||||
<div class="history-item-header">
|
||||
<h4 class="history-item-title">{{ item.title || '未命名' }}</h4>
|
||||
</div>
|
||||
<div class="history-item-file-row">
|
||||
<svg
|
||||
class="history-file-icon"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M3 2C2.44772 2 2 2.44772 2 3V13C2 13.5523 2.44772 14 3 14H13C13.5523 14 14 13.5523 14 13V5.41421C14 5.149 13.8946 4.89464 13.7071 4.70711L11.2929 2.29289C11.1054 2.10536 10.851 2 10.5858 2H3Z"
|
||||
fill="currentColor"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<path
|
||||
d="M3 2C2.44772 2 2 2.44772 2 3V13C2 13.5523 2.44772 14 3 14H13C13.5523 14 14 13.5523 14 13V5.41421C14 5.149 13.8946 4.89464 13.7071 4.70711L11.2929 2.29289C11.1054 2.10536 10.851 2 10.5858 2H3Z"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M10 2V5H13"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5 8H11M5 10H9"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
<span class="history-item-file">{{ item.file_name || '未命名文件' }}</span>
|
||||
</div>
|
||||
<div class="history-item-time-row">
|
||||
<span class="history-item-time-label">生成时间:</span>
|
||||
<span class="history-item-time">{{ item.created_at || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧操作 -->
|
||||
<div class="history-item-right">
|
||||
<Button
|
||||
v-if="item.params"
|
||||
type="link"
|
||||
size="small"
|
||||
class="history-btn-link"
|
||||
@click="handleViewJson(item)"
|
||||
>
|
||||
<i class="fa-solid fa-code mr-1"></i>
|
||||
查看
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
class="history-btn-primary"
|
||||
@click="handleDownloadHistory(item)"
|
||||
>
|
||||
<i class="fa-solid fa-download mr-1"></i>
|
||||
下载
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
<!-- JSON详情查看Modal -->
|
||||
<Modal
|
||||
v-model:open="jsonViewerVisible"
|
||||
title="生成参数详情"
|
||||
:width="800"
|
||||
:footer="null"
|
||||
class="json-viewer-modal"
|
||||
>
|
||||
<div class="json-viewer-container">
|
||||
<JsonViewer
|
||||
:value="currentJsonData"
|
||||
:expand-depth="3"
|
||||
copyable
|
||||
boxed
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
@@ -153,4 +348,168 @@ const handleGenerate = async (data: CodeGenData) => {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
/* 历史记录列表样式 - 简洁美观风格 */
|
||||
.history-list-clean {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.history-item-clean {
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
transition: all 0.2s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dark .history-item-clean {
|
||||
background: #1f2937;
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.history-item-clean:hover {
|
||||
border-color: rgba(24, 144, 255, 0.3);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.dark .history-item-clean:hover {
|
||||
border-color: rgba(24, 144, 255, 0.5);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.history-item-wrapper {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: 18px 20px;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.history-item-left {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.history-item-header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.history-item-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
line-height: 1.4;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dark .history-item-title {
|
||||
color: #f9fafb;
|
||||
}
|
||||
|
||||
.history-item-file-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.history-file-icon {
|
||||
color: #1890ff;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.history-item-file {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
word-break: break-all;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.dark .history-item-file {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.history-item-time-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.history-item-time-label {
|
||||
font-size: 13px;
|
||||
color: #9ca3af;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dark .history-item-time-label {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.history-item-time {
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dark .history-item-time {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.history-item-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.history-btn-link {
|
||||
height: auto;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.history-btn-primary {
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.history-btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* JSON查看器样式 */
|
||||
.json-viewer-container {
|
||||
max-height: 600px;
|
||||
overflow: auto;
|
||||
padding: 8px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dark .json-viewer-container {
|
||||
background: #1f2937;
|
||||
}
|
||||
|
||||
/* 抽屉样式优化 */
|
||||
:deep(.history-drawer .ant-drawer-body) {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user