feat: 收敛AI资源发布审批生命周期
- 统一工作流、知识库、聊天助手的发布、重新发布、下线与删除链路 - 收敛审批编排、生命周期状态机与展示态,补齐审批管理和快照预览 - 调整审批管理权限模型为单入口页面加内部按钮权限
This commit is contained in:
@@ -1,22 +1,87 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
import { ElButton, ElEmpty, ElImage, ElScrollbar } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
const dialogVisible = ref(false);
|
||||
const data = ref<any>();
|
||||
function openDialog(row: any) {
|
||||
const docPreviewLoading = ref(false);
|
||||
const docPreviewContent = ref('');
|
||||
const docPreviewTruncated = ref(false);
|
||||
const docPreviewError = ref('');
|
||||
let previewRequestId = 0;
|
||||
|
||||
const isDocument = computed(() => data.value?.resourceType === 3);
|
||||
const fileName = computed(() => {
|
||||
const resourceName = data.value?.resourceName || '';
|
||||
const suffix = data.value?.suffix || '';
|
||||
return suffix ? `${resourceName}.${suffix}` : resourceName;
|
||||
});
|
||||
const previewWidth = computed(() => (isDocument.value ? 'xl' : 'md'));
|
||||
|
||||
async function openDialog(row: any) {
|
||||
data.value = row;
|
||||
dialogVisible.value = true;
|
||||
resetDocumentPreview();
|
||||
if (row?.resourceType === 3) {
|
||||
await loadDocumentPreview(row);
|
||||
}
|
||||
}
|
||||
function closeDialog() {
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
|
||||
function resetDocumentPreview() {
|
||||
docPreviewLoading.value = false;
|
||||
docPreviewContent.value = '';
|
||||
docPreviewTruncated.value = false;
|
||||
docPreviewError.value = '';
|
||||
}
|
||||
|
||||
async function loadDocumentPreview(row: any) {
|
||||
if (!row?.id) {
|
||||
docPreviewError.value = '当前素材缺少预览标识,请下载后查看';
|
||||
return;
|
||||
}
|
||||
const currentRequestId = ++previewRequestId;
|
||||
docPreviewLoading.value = true;
|
||||
try {
|
||||
const res = await api.get('/api/v1/resource/previewContent', {
|
||||
params: { id: row.id },
|
||||
});
|
||||
if (currentRequestId !== previewRequestId) {
|
||||
return;
|
||||
}
|
||||
docPreviewContent.value = res.data?.content || '';
|
||||
docPreviewTruncated.value = !!res.data?.truncated;
|
||||
if (!docPreviewContent.value) {
|
||||
docPreviewError.value = '暂未提取到可预览内容,请下载后查看';
|
||||
}
|
||||
} catch {
|
||||
if (currentRequestId !== previewRequestId) {
|
||||
return;
|
||||
}
|
||||
docPreviewError.value = '文档预览加载失败,请下载后查看';
|
||||
} finally {
|
||||
if (currentRequestId === previewRequestId) {
|
||||
docPreviewLoading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openSourceFile() {
|
||||
if (data.value?.resourceUrl) {
|
||||
window.open(data.value.resourceUrl, '_blank');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -24,25 +89,119 @@ function closeDialog() {
|
||||
v-model:open="dialogVisible"
|
||||
:title="$t('message.preview')"
|
||||
:before-close="closeDialog"
|
||||
width="md"
|
||||
:width="previewWidth"
|
||||
:show-footer="false"
|
||||
>
|
||||
<div class="flex justify-center">
|
||||
<div class="resource-preview flex justify-center">
|
||||
<ElImage
|
||||
v-if="data.resourceType === 0"
|
||||
style="width: 200px"
|
||||
:preview-src-list="[data.resourceUrl]"
|
||||
:src="data.resourceUrl"
|
||||
/>
|
||||
<video v-if="data.resourceType === 1" controls width="640" height="360">
|
||||
<video
|
||||
v-else-if="data.resourceType === 1"
|
||||
controls
|
||||
width="640"
|
||||
height="360"
|
||||
>
|
||||
<source :src="data.resourceUrl" type="video/mp4" />
|
||||
{{ $t('message.notVideo') }}
|
||||
</video>
|
||||
<audio v-if="data.resourceType === 2" controls :src="data.resourceUrl">
|
||||
<audio
|
||||
v-else-if="data.resourceType === 2"
|
||||
controls
|
||||
class="mt-8 w-full max-w-[640px]"
|
||||
:src="data.resourceUrl"
|
||||
>
|
||||
{{ $t('message.notAudio') }}
|
||||
</audio>
|
||||
<div
|
||||
v-else-if="isDocument"
|
||||
v-loading="docPreviewLoading"
|
||||
:element-loading-text="$t('message.loading')"
|
||||
class="resource-preview__document bg-background border-border w-full rounded-xl border"
|
||||
>
|
||||
<div
|
||||
class="resource-preview__toolbar border-border flex items-center justify-between gap-3 border-b px-5 py-4"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<div class="truncate text-sm font-medium">{{ fileName }}</div>
|
||||
<div
|
||||
v-if="docPreviewTruncated"
|
||||
class="text-muted-foreground mt-1 text-xs"
|
||||
>
|
||||
内容较长,当前仅展示前 20000 个字符
|
||||
</div>
|
||||
</div>
|
||||
<ElButton link type="primary" @click="openSourceFile">
|
||||
{{ $t('button.download') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
<div class="resource-preview__body">
|
||||
<ElEmpty
|
||||
v-if="docPreviewError"
|
||||
:description="docPreviewError"
|
||||
class="resource-preview__empty"
|
||||
>
|
||||
<ElButton link type="primary" @click="openSourceFile">
|
||||
{{ $t('button.download') }}
|
||||
</ElButton>
|
||||
</ElEmpty>
|
||||
<ElScrollbar
|
||||
v-else
|
||||
class="resource-preview__scrollbar"
|
||||
wrap-class="resource-preview__scrollbar-wrap"
|
||||
>
|
||||
<pre class="resource-preview__content">{{
|
||||
docPreviewContent
|
||||
}}</pre>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
.resource-preview {
|
||||
min-height: 220px;
|
||||
}
|
||||
|
||||
.resource-preview__document {
|
||||
min-height: 540px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.resource-preview__toolbar {
|
||||
min-height: 72px;
|
||||
}
|
||||
|
||||
.resource-preview__body {
|
||||
height: 468px;
|
||||
}
|
||||
|
||||
.resource-preview__scrollbar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.resource-preview__scrollbar-wrap) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.resource-preview__content {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
font-family:
|
||||
'SFMono-Regular', 'JetBrains Mono', 'Fira Code', Consolas, 'Liberation Mono',
|
||||
monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.75;
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.resource-preview__empty {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user