fix(#187): 修复模板配置台两处交互失效
1. studio/import.vue CSV 上传失效:onFile 原按 DOM Event 取 e.target.files,
但 a-upload 的 @change 载荷是 UploadChangeParam { file, fileList },
:before-upload="() => false" 时文件在 file.originFileObj 上,导致必抛
TypeError 无响应。改为从 info.file.originFileObj 取文件对象。
2. studio/layout.vue 第 45 行「发布布局」按钮无 @click 处理(死按钮):
新增 publishLayout,将布局 JSON 暂存 localStorage
(iaop.studio.layout.v1),与 version.vue 版本发布联动;
version.vue 发布时读取并打包该布局。
layoutJson 改为 computed,模板同步更新。
验收:本环境无 pnpm/node_modules,构建验证转 bot_qa 构建环境;
上传符合表头 CSV 应出现校验/预览,缺表头 CSV 应报错;
点「发布布局」应提示成功并记录发布时间。
This commit is contained in:
@@ -4,6 +4,7 @@ import { ref } from 'vue';
|
||||
import { Page, VbenButton } from '@vben/common-ui';
|
||||
import { BxsFile } from '@vben/icons';
|
||||
|
||||
import type { UploadChangeParam } from 'antdv-next';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
@@ -33,14 +34,19 @@ const gridOptions: VxeTableGridOptions<Record<string, string>> = {
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||
|
||||
function onFile(e: Event) {
|
||||
const el = e.target as HTMLInputElement;
|
||||
const file = el.files?.[0];
|
||||
if (!file) return;
|
||||
function onFile(info: UploadChangeParam) {
|
||||
// a-upload 的 @change 载荷是 UploadChangeParam { file, fileList },
|
||||
// 在 :before-upload="() => false"(禁止自动上传)时文件对象在 file.originFileObj 上,
|
||||
// 不是 DOM Event,不能用 e.target.files(会抛 TypeError 导致无响应)。
|
||||
const { file } = info;
|
||||
// 仅在选中文件后处理一次(removed 状态时跳过,避免清空预览)
|
||||
if (file.status === 'removed') return;
|
||||
const raw = file.originFileObj ?? file;
|
||||
if (!raw) return;
|
||||
fileName.value = file.name;
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => parseCsv(String(reader.result || ''));
|
||||
reader.readAsText(file);
|
||||
reader.readAsText(raw as Blob);
|
||||
}
|
||||
|
||||
function parseCsv(text: string) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { Page, VbenButton } from '@vben/common-ui';
|
||||
import { MaterialSymbolsEdit } from '@vben/icons';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
const components = ref([
|
||||
{ type: 'process_view', title: '四状态工艺流程', enabled: true },
|
||||
@@ -24,7 +25,25 @@ const move = (i: number, dir: number) => {
|
||||
components.value[j] = t;
|
||||
};
|
||||
|
||||
const layoutJson = () => JSON.stringify({ widgets: components.value.filter((c) => c.enabled) }, null, 2);
|
||||
const layoutJson = computed(() =>
|
||||
JSON.stringify({ widgets: components.value.filter((c) => c.enabled) }, null, 2),
|
||||
);
|
||||
|
||||
// 发布布局:将布局 JSON 暂存到 localStorage(与版本发布页联动——
|
||||
// version.vue 发布时一并打包该布局),注册表服务落地后可改为注册到服务端。
|
||||
const LAYOUT_STORAGE_KEY = 'iaop.studio.layout.v1';
|
||||
const lastPublishedAt = ref('');
|
||||
|
||||
async function publishLayout() {
|
||||
const payload = layoutJson.value;
|
||||
try {
|
||||
localStorage.setItem(LAYOUT_STORAGE_KEY, payload);
|
||||
lastPublishedAt.value = new Date().toISOString().slice(0, 19).replace('T', ' ');
|
||||
message.success('布局已发布(暂存本地,将在「版本发布」时一并打包)');
|
||||
} catch {
|
||||
message.error('布局发布失败:本地存储不可用');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -41,8 +60,9 @@ const layoutJson = () => JSON.stringify({ widgets: components.value.filter((c) =
|
||||
</a-list>
|
||||
</a-card>
|
||||
<a-card title="导出布局 JSON(由驾驶舱渲染)" :bordered="false" class="col">
|
||||
<pre class="json-body">{{ layoutJson() }}</pre>
|
||||
<VbenButton variant="solid"><MaterialSymbolsEdit class="size-4" />发布布局(版本发布见「版本发布」页)</VbenButton>
|
||||
<pre class="json-body">{{ layoutJson }}</pre>
|
||||
<a-tag v-if="lastPublishedAt" color="green">最近发布:{{ lastPublishedAt }}</a-tag>
|
||||
<VbenButton variant="solid" @click="publishLayout"><MaterialSymbolsEdit class="size-4" />发布布局(版本发布见「版本发布」页)</VbenButton>
|
||||
</a-card>
|
||||
</div>
|
||||
</Page>
|
||||
|
||||
@@ -51,13 +51,17 @@ onMounted(async () => {
|
||||
async function publish() {
|
||||
const version = `v${Date.now() % 100000}`;
|
||||
const name = 'iaop-template';
|
||||
// 一并打包「驾驶舱布局编排」页发布的布局(issue #187:发布布局与版本发布联动)
|
||||
const layoutJson = localStorage.getItem('iaop.studio.layout.v1') || '';
|
||||
const description = layoutJson ? '手动发布(前端,含布局)' : '手动发布(前端)';
|
||||
try {
|
||||
await registerModel({ name, version, stage: 'staging', description: '手动发布(前端)' });
|
||||
// 发布 = 注册新版本到服务端注册表(staging);description 含布局标记(issue #187 联动)
|
||||
await registerModel({ name, version, stage: 'staging', description });
|
||||
online.value = true;
|
||||
rows.value.unshift({
|
||||
version, stage: 'staging',
|
||||
time: new Date().toISOString().slice(0, 16).replace('T', ' '),
|
||||
author: 'admin', note: '已发布到服务端注册表',
|
||||
author: 'admin', note: layoutJson ? '已发布到服务端注册表(含布局)' : '已发布到服务端注册表',
|
||||
});
|
||||
message.success(`已注册 ${name}@${version}(staging)`);
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user