<script lang="ts" setup>
|
import type { FormInstance } from 'ant-design-vue';
|
|
import { computed, reactive, ref, toRefs } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { ModalClose } from '@jnpf/ui/modal';
|
|
import { Modal as AModal } from 'ant-design-vue';
|
|
import { upload } from '#/api/core/common';
|
import { upload as reportUpload } from '#/api/onlineDev/report';
|
import { getMenuSelector } from '#/api/system/menu';
|
import { $t } from '#/locales';
|
|
interface State {
|
confirmLoading: boolean;
|
dataForm: any;
|
rules: any;
|
treeOptions: any[];
|
visible: boolean;
|
}
|
|
defineOptions({ inheritAttrs: false, name: 'JnpfUploadBtn' });
|
const props = defineProps({
|
accept: { default: '*', type: String },
|
buttonText: { default: '', type: String },
|
buttonType: { default: 'link', type: String },
|
data: { default: () => {}, type: Object },
|
showIcon: { default: true, type: Boolean },
|
type: { default: '', type: String },
|
url: { default: '', type: String },
|
});
|
const emit = defineEmits(['onSuccess']);
|
const { createMessage } = useMessage();
|
const formElRef = ref<FormInstance>();
|
const state = reactive<State>({
|
confirmLoading: false,
|
dataForm: {
|
fileList: [],
|
parentId: '',
|
type: 0,
|
},
|
rules: {
|
fileList: [{ message: '必填', required: true, trigger: 'change' }],
|
parentId: [{ message: '必填', required: true, trigger: 'change' }],
|
type: [{ message: '必填', required: true, trigger: 'change', type: 'number' }],
|
},
|
treeOptions: [],
|
visible: false,
|
});
|
const { confirmLoading, dataForm, rules, treeOptions, visible } = toRefs(state);
|
const hideList = ['/system/DataModel', '/system/DataInterfaceVariate'];
|
|
const getTipText = computed(() => `一次只能导入一个文件,文件后缀名必须是${props.accept}。`);
|
const getIsHideType = computed(() => hideList.some((o) => props.url.includes(o)));
|
|
function openModal() {
|
state.confirmLoading = false;
|
state.visible = true;
|
state.dataForm = {
|
fileList: [],
|
parentId: '',
|
type: 0,
|
};
|
if (props.type == 'menu') getMenuSelectorList();
|
}
|
function getMenuSelectorList() {
|
getMenuSelector({ category: props.data.category }).then((res) => {
|
state.treeOptions = [
|
{
|
fullName: '顶级节点',
|
hasChildren: true,
|
id: '-1',
|
children: res.data.list,
|
},
|
];
|
});
|
}
|
async function handleSubmit() {
|
try {
|
const values = await formElRef.value?.validate();
|
if (!values) return;
|
if (!props.url) return;
|
const formData = new FormData();
|
formData.append('file', state.dataForm.fileList[0]);
|
formData.append('type', values.type);
|
for (const [key, value] of Object.entries(props.data || {})) {
|
formData.append(key, value);
|
}
|
if (props.type == 'menu') formData.append('parentId', values.parentId);
|
state.confirmLoading = true;
|
const uploadMethod = props.type == 'report' ? reportUpload : upload;
|
uploadMethod(props.url, formData)
|
.then((res) => {
|
createMessage.success(res.msg);
|
emit('onSuccess');
|
state.confirmLoading = false;
|
state.visible = false;
|
})
|
.catch(() => {
|
state.confirmLoading = false;
|
});
|
} catch {}
|
}
|
function handleCancel() {
|
state.visible = false;
|
}
|
function handleRemove() {
|
state.dataForm.fileList = [];
|
}
|
function beforeUpload(file) {
|
const isAccept = checkAccept(file);
|
if (!isAccept) {
|
createMessage.error({ content: `请选择${props.accept}类型的文件`, key: 'upload' });
|
return isAccept;
|
}
|
state.dataForm.fileList = [file];
|
return false;
|
}
|
// 校验格式
|
function checkAccept(file) {
|
if (!props.accept || props.accept === '*') return true;
|
const extension = file.name.slice(Math.max(0, file.name.lastIndexOf('.')));
|
if (props.accept.includes(extension)) return true;
|
return false;
|
}
|
</script>
|
|
<template>
|
<div class="common-container">
|
<a-button :pre-icon="showIcon ? 'icon-ym icon-ym-btn-upload' : ''" :type="buttonType" @click="openModal">
|
{{ buttonText || $t('common.importText') }}
|
</a-button>
|
<AModal
|
v-model:open="visible"
|
:confirm-loading="confirmLoading"
|
:mask-closable="false"
|
:title="buttonText || $t('common.importText')"
|
:width="600"
|
centered
|
destroy-on-close
|
@cancel="handleCancel"
|
@ok="handleSubmit">
|
<template #closeIcon>
|
<ModalClose :can-fullscreen="false" @cancel="handleCancel" />
|
</template>
|
<div class="px-10 py-[20px]">
|
<a-form ref="formElRef" :colon="false" :label-col="{ style: { width: '90px' } }" :model="dataForm" :rules="rules" label-align="right">
|
<a-form-item v-if="type == 'menu'" label="上级菜单" name="parentId">
|
<jnpf-tree-select v-model:value="dataForm.parentId" :last-level="props.data.category == 'App'" :options="treeOptions" placeholder="请选择" />
|
</a-form-item>
|
<a-form-item v-if="!getIsHideType" label="识别重复" name="type">
|
<a-radio-group v-model:value="dataForm.type" class="common-radio">
|
<a-radio :value="0">跳过<BasicHelp text="当导入数据不存在,作为新数据导入;数据已存在,不做处理" /></a-radio>
|
<a-radio :value="1">追加<BasicHelp text="当导入数据已存在,增加相同记录新数据,名称和编码自动增加随机码" /></a-radio>
|
</a-radio-group>
|
</a-form-item>
|
<a-form-item label="上传文件" name="fileList">
|
<a-upload :accept="accept" :before-upload="beforeUpload" :file-list="dataForm.fileList" @remove="handleRemove">
|
<a-button pre-icon="icon-ym icon-ym-btn-upload">上传文件</a-button>
|
<div class="upload-file__tip">{{ getTipText }}</div>
|
</a-upload>
|
</a-form-item>
|
</a-form>
|
</div>
|
</AModal>
|
</div>
|
</template>
|
<style lang="scss" scoped>
|
.upload-file__tip {
|
margin-top: 5px;
|
font-size: 12px;
|
line-height: 1.2;
|
color: var(--text-color-secondary);
|
word-break: break-all;
|
}
|
</style>
|