feat: 项目管理添加网路图

This commit is contained in:
caiyuchao
2025-09-17 17:59:19 +08:00
parent cf98f7579b
commit ede917ad9f
6 changed files with 128 additions and 9 deletions

View File

@@ -26,6 +26,8 @@ export namespace ProjectApi {
softwareVersion: number; // 软件版本信息
remark: string; // 备注
serialNo?: string; // 序列号
file?: any; // 上传的文件
fileUrl?: string; // 文件访问地址
}
}

View File

@@ -24,5 +24,8 @@
"updateTime": "Last Modified Time",
"commentNum": "Comment Count",
"softwareVersion": "Software Version",
"operatingSystem": "Operating System Platform"
"operatingSystem": "Operating System Platform",
"networkChart": "Network Chart",
"uploadFile": "Click to Upload File",
"uploadRule": "Please upload {0}"
}

View File

@@ -24,5 +24,8 @@
"updateTime": "最后修改时间",
"commentNum": "进展记录数",
"softwareVersion": "软件版本",
"operatingSystem": "操作系统平台"
"operatingSystem": "操作系统平台",
"networkChart": "网路图",
"uploadFile": "点击上传文件",
"uploadRule": "请上传{0}"
}

View File

@@ -247,6 +247,29 @@ export function useFormSchema(): VbenFormSchema[] {
options: getDictOptions(DICT_TYPE.LIC_SOFTWARE_VERSION, 'number'),
},
},
{
component: 'Upload',
fieldName: 'file',
label: $t('project.networkChart'),
help: '提供对应项目的组网图,且不超过 5MB',
dependencies: {
triggerFields: ['customerId'],
rules: (values) => {
return z.any().refine(
(file) => {
if (values.customerId === 13) {
// 编辑状态且没有更改图片时,不校验
return true;
}
return file instanceof File;
},
{
message: $t('project.uploadRule', [$t('project.networkChart')]),
},
);
},
},
},
{
fieldName: 'remark',
label: $t('project.remarks'),
@@ -520,6 +543,12 @@ export function useGridColumns(
props: { type: DICT_TYPE.LIC_SOFTWARE_VERSION },
},
},
{
field: 'file-content',
title: $t('project.networkChart'),
minWidth: 120,
slots: { default: 'file-content' },
},
{
field: 'remark',
title: $t('project.remarks'),

View File

@@ -6,9 +6,9 @@ import type {
import type { ProjectApi } from '#/api/license/project';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart } from '@vben/utils';
import { downloadFileFromBlobPart, openWindow } from '@vben/utils';
import { message } from 'ant-design-vue';
import { Button, Image, message } from 'ant-design-vue';
import dayjs from 'dayjs';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
@@ -213,6 +213,23 @@ const [Grid, gridApi] = useVbenVxeGrid({
]"
/>
</template>
<template #file-content="{ row }">
<Image
v-if="
row.fileUrl &&
(row.fileUrl.includes('.jpg') ||
row.fileUrl.includes('.png') ||
row.fileUrl.includes('.gif') ||
row.fileUrl.includes('.webp') ||
row.fileUrl.includes('.jpeg') ||
row.fileUrl.includes('.svg'))
"
:src="row.fileUrl"
/>
<Button v-else type="link" @click="() => openWindow(row.fileUrl)">
{{ row.fileUrl ? '下载' : '' }}
</Button>
</template>
</Grid>
</Page>
</template>

View File

@@ -1,11 +1,14 @@
<script lang="ts" setup>
import type { UploadProps } from 'ant-design-vue';
import type { FileType } from 'ant-design-vue/es/upload/interface';
import type { ProjectApi } from '#/api/license/project';
import { computed } from 'vue';
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { message, Upload } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
@@ -14,11 +17,15 @@ import {
getProject,
updateProject,
} from '#/api/license/project';
import { useUpload } from '#/components/upload/use-upload';
import { $t } from '#/locales';
import { formData, useFormSchema } from '../data';
const emit = defineEmits(['success']);
const fileList = ref<UploadProps['fileList']>([]);
const getTitle = computed(() => {
return formData.value?.id
? $t('ui.actionTitle.edit', [$t('project.project')])
@@ -42,14 +49,30 @@ const [Form, formApi] = useVbenForm({
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
const data = (await formApi.getValues()) as ProjectApi.Project;
if (data.fileUrl && !data.file) {
formApi.setFieldValue(
'file',
new File(['Hello, world!'], 'example.txt', { type: 'text/plain' }),
);
}
const { valid } = await formApi.validate();
if (!valid) {
return;
}
if (data.fileUrl && !data.file) {
data.file = undefined;
}
modalApi.lock();
// 提交表单
const data = (await formApi.getValues()) as ProjectApi.Project;
try {
// 先上传文件
if (data.file) {
data.fileUrl = await useUpload().httpRequest(data.file);
}
// if (data.fileUrl) {
// await formApi.validateField('file');
// }
await (formData.value?.id ? updateProject(data) : createProject(data));
// 关闭并提示
await modalApi.close();
@@ -77,22 +100,64 @@ const [Modal, modalApi] = useVbenModal({
data.endTime = data.endTime ? data.endTime.toString() : '';
// 设置到 values
formData.value = data;
fileList.value = data.fileUrl
? [
{
uid: '-1',
name: data.fileUrl.slice(
Math.max(0, data.fileUrl.lastIndexOf('/') + 1),
),
status: 'done',
url: data.fileUrl,
},
]
: [];
await formApi.setValues(formData.value);
await formApi.validateField('contractCode');
await formApi.validateField('customerOwner');
// 设置最大SN
const maxSn = await getMaxSn();
if (!formData.value?.code) {
formApi.setFieldValue('code', maxSn);
}
formApi.setFieldValue('fileUrl', data.fileUrl || '');
modalApi.setState({ loading: false });
},
});
/** 上传前 */
function beforeUpload(file: FileType) {
const isLtM = file.size / 1024 / 1024 < 5;
if (!isLtM) {
message.error('文件大小不能超过 5MB!');
return Upload.LIST_IGNORE;
}
formApi.setFieldValue('file', file);
return false;
}
</script>
<template>
<Modal :title="getTitle" class="w-1/2">
<Form class="mx-4" />
<Form class="mx-4">
<template #file>
<div class="w-full">
<!-- 上传区域 -->
<Upload.Dragger
name="file"
:max-count="1"
:before-upload="beforeUpload"
v-model:file-list="fileList"
>
<!-- <p class="ant-upload-drag-icon">
<span class="icon-[ant-design--inbox-outlined] text-2xl"></span>
</p> -->
<p class="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p class="ant-upload-hint">提供对应项目的组网图</p>
</Upload.Dragger>
</div>
</template>
</Form>
</Modal>
</template>