272 lines
8.9 KiB
Vue
272 lines
8.9 KiB
Vue
<template>
|
||
<div class="modern-page-container">
|
||
<div class="page-wrapper">
|
||
<el-card class="content-card" shadow="never">
|
||
<template #header>
|
||
<div class="card-header">
|
||
|
||
<div class="header-actions">
|
||
<el-button
|
||
type="primary"
|
||
icon="FolderAdd"
|
||
@click="openUploadDialog()"
|
||
v-auth="'purchase_template_add'">
|
||
新增模板
|
||
</el-button>
|
||
<el-alert type="info" :closable="false" class="mb3 mt-3" show-icon>
|
||
此处模版中的模版编码对应用户端下载模版匹配,请勿随意修改或删除。正常情况下如有发生模版变化,重新上传即可。如有新增模版,请联系管理员进行处理。
|
||
</el-alert>
|
||
</div>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<el-table :data="tableData" v-loading="loading" stripe class="modern-table">
|
||
<el-table-column type="index" label="序号" width="70" align="center">
|
||
<template #header>
|
||
<el-icon><List /></el-icon>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="templateTitle" label="模板类型名称" min-width="180" show-overflow-tooltip />
|
||
<el-table-column prop="templateType" label="模板类型编码" min-width="180" show-overflow-tooltip />
|
||
<el-table-column prop="templateName" label="模板名称" min-width="220" show-overflow-tooltip />
|
||
<el-table-column prop="updateTime" label="更新时间" width="180" show-overflow-tooltip />
|
||
<el-table-column label="操作" width="260" align="center" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button
|
||
type="primary"
|
||
link
|
||
icon="Download"
|
||
@click="handleDownload(row)"
|
||
v-auth="'purchase_template_view'">
|
||
下载
|
||
</el-button>
|
||
<el-button
|
||
type="primary"
|
||
link
|
||
icon="UploadFilled"
|
||
@click="openUploadDialog(row)"
|
||
v-auth="'purchase_template_add'">
|
||
重新上传
|
||
</el-button>
|
||
<el-button
|
||
type="primary"
|
||
link
|
||
icon="Edit"
|
||
@click="openEditDialog(row)"
|
||
v-auth="'purchase_template_add'">
|
||
编辑
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-card>
|
||
|
||
<el-dialog v-model="uploadDialogVisible" title="上传模板" width="450px" destroy-on-close>
|
||
<el-form :model="uploadForm" label-width="100px">
|
||
<el-form-item label="模板类型编码" required>
|
||
<el-input
|
||
v-model="uploadForm.templateType"
|
||
placeholder="例如: business_negotiation, inquiry"
|
||
:disabled="!!uploadForm.lockType"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="模板类型名称">
|
||
<el-input
|
||
v-model="uploadForm.templateTitle"
|
||
placeholder="例如: 部门采购询价模版"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="模板文件" required>
|
||
<el-upload
|
||
class="upload-block"
|
||
:auto-upload="false"
|
||
:limit="1"
|
||
:file-list="fileList"
|
||
:on-change="handleFileChange"
|
||
:on-remove="handleFileRemove"
|
||
>
|
||
<el-button type="primary" icon="UploadFilled">选择文件</el-button>
|
||
<template #tip>
|
||
<div class="el-upload__tip">支持 doc、docx 等 Word 模板文件,上传后前端下载将使用该文件。</div>
|
||
</template>
|
||
</el-upload>
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="uploadDialogVisible = false">取 消</el-button>
|
||
<el-button type="primary" :loading="uploading" @click="handleUploadConfirm">上 传</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-dialog v-model="editDialogVisible" title="编辑模板" width="420px" destroy-on-close>
|
||
<el-form :model="editForm" label-width="100px">
|
||
<el-form-item label="模板类型编码">
|
||
<el-input v-model="editForm.templateType" disabled />
|
||
</el-form-item>
|
||
<el-form-item label="模板类型名称" required>
|
||
<el-input v-model="editForm.templateTitle" placeholder="请输入模板类型名称" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="editDialogVisible = false">取 消</el-button>
|
||
<el-button type="primary" :loading="editing" @click="handleEditConfirm">保 存</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts" name="PurchasingTemplateManage">
|
||
import { ref, reactive, onMounted } from 'vue';
|
||
import { Document, List, UploadFilled, Download, Edit } from '@element-plus/icons-vue';
|
||
import { listTemplates, uploadTemplate, getTemplateDownloadUrl, updateTemplateTitle } from '/@/api/purchase/purchasingtemplate';
|
||
import { useMessage } from '/@/hooks/message';
|
||
|
||
const loading = ref(false);
|
||
const tableData = ref<any[]>([]);
|
||
|
||
const uploadDialogVisible = ref(false);
|
||
const uploading = ref(false);
|
||
const uploadForm = reactive<{
|
||
templateType: string;
|
||
templateTitle: string;
|
||
lockType?: boolean;
|
||
}>({
|
||
templateType: '',
|
||
templateTitle: '',
|
||
lockType: false,
|
||
});
|
||
const editDialogVisible = ref(false);
|
||
const editing = ref(false);
|
||
const editForm = reactive<{
|
||
id: number | null;
|
||
templateType: string;
|
||
templateTitle: string;
|
||
}>({
|
||
id: null,
|
||
templateType: '',
|
||
templateTitle: '',
|
||
});
|
||
|
||
const fileList = ref<any[]>([]);
|
||
const currentFile = ref<File | null>(null);
|
||
|
||
const fetchData = async () => {
|
||
loading.value = true;
|
||
try {
|
||
const res = await listTemplates();
|
||
tableData.value = (res && res.data) || [];
|
||
} catch (e) {
|
||
tableData.value = [];
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(fetchData);
|
||
|
||
const openUploadDialog = (row?: any) => {
|
||
uploadDialogVisible.value = true;
|
||
uploadForm.templateType = row?.templateType || '';
|
||
uploadForm.templateTitle = row?.templateTitle || '';
|
||
uploadForm.lockType = !!row?.templateType;
|
||
fileList.value = [];
|
||
currentFile.value = null;
|
||
};
|
||
|
||
const handleFileChange = (file: any, files: any[]) => {
|
||
fileList.value = files.slice(-1);
|
||
currentFile.value = file.raw || null;
|
||
};
|
||
|
||
const handleFileRemove = () => {
|
||
fileList.value = [];
|
||
currentFile.value = null;
|
||
};
|
||
|
||
const handleUploadConfirm = async () => {
|
||
if (!uploadForm.templateType || !uploadForm.templateType.trim()) {
|
||
useMessage().error('请填写模板类型编码');
|
||
return;
|
||
}
|
||
if (!currentFile.value) {
|
||
useMessage().error('请选择要上传的模板文件');
|
||
return;
|
||
}
|
||
uploading.value = true;
|
||
try {
|
||
const formData = new FormData();
|
||
formData.append('type', uploadForm.templateType.trim());
|
||
if (uploadForm.templateTitle && uploadForm.templateTitle.trim()) {
|
||
formData.append('title', uploadForm.templateTitle.trim());
|
||
}
|
||
formData.append('file', currentFile.value);
|
||
await uploadTemplate(formData);
|
||
useMessage().success('模板上传成功');
|
||
uploadDialogVisible.value = false;
|
||
await fetchData();
|
||
} catch (e) {
|
||
useMessage().error('模板上传失败');
|
||
} finally {
|
||
uploading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleDownload = async (row: any) => {
|
||
if (!row?.templateType) {
|
||
useMessage().error('缺少模板类型编码');
|
||
return;
|
||
}
|
||
const url = getTemplateDownloadUrl(row.templateType);
|
||
const fileName = row.templateName || row.templateTitle || row.templateType;
|
||
try {
|
||
await (window as any).other?.downBlobFile?.(url, {}, fileName) ||
|
||
// 兼容直接使用工具函数
|
||
(await import('/@/utils/other')).default.downBlobFile(url, {}, fileName);
|
||
} catch (e) {
|
||
// 如果工具函数不可用,则退回 window.open
|
||
window.open(url, '_blank');
|
||
}
|
||
};
|
||
|
||
const openEditDialog = (row: any) => {
|
||
editDialogVisible.value = true;
|
||
editForm.id = row?.id ?? null;
|
||
editForm.templateType = row?.templateType || '';
|
||
editForm.templateTitle = row?.templateTitle || '';
|
||
};
|
||
|
||
const handleEditConfirm = async () => {
|
||
if (!editForm.id) {
|
||
useMessage().error('缺少模板ID');
|
||
return;
|
||
}
|
||
if (!editForm.templateTitle || !editForm.templateTitle.trim()) {
|
||
useMessage().error('请输入模板类型名称');
|
||
return;
|
||
}
|
||
editing.value = true;
|
||
try {
|
||
await updateTemplateTitle({
|
||
id: editForm.id,
|
||
templateTitle: editForm.templateTitle.trim(),
|
||
});
|
||
useMessage().success('保存成功');
|
||
editDialogVisible.value = false;
|
||
await fetchData();
|
||
} catch (e) {
|
||
useMessage().error('保存失败');
|
||
} finally {
|
||
editing.value = false;
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.upload-block {
|
||
display: inline-block;
|
||
}
|
||
</style>
|
||
|