452 lines
13 KiB
Vue
452 lines
13 KiB
Vue
<template>
|
||
<!-- 废标项库页面 -->
|
||
<el-card class="rejection-item-container">
|
||
<!-- 返回按钮 -->
|
||
<div class="back-container">
|
||
<el-button type="default" size="small" @click="handleBack" class="back-btn">
|
||
返回
|
||
</el-button>
|
||
</div>
|
||
|
||
<!-- 数据列表:完全依赖TableModel的内置搜索 -->
|
||
<div class="table-container">
|
||
<TableModel
|
||
:formLabel="formLabel"
|
||
:showOperation="true"
|
||
:showRightTools="false"
|
||
ref="rejectionItemTableRef"
|
||
:columnsList="columnsList"
|
||
:sendParams="{ enterpriseId: enterpriseId }"
|
||
:request-api="listRejectionItem"
|
||
>
|
||
<template slot="tableTitle">
|
||
<h3>数据列表</h3>
|
||
</template>
|
||
<template slot="tableActions">
|
||
<el-button
|
||
@click="handleAdd"
|
||
v-hasPermi="['enterpriseLibrary:rejectionItem:add']"
|
||
class="add-btn"
|
||
>
|
||
<i class="el-icon-plus"></i> 新增废标项
|
||
</el-button>
|
||
<el-button type="primary" class="import-btn" @click="handleImport">导入</el-button>
|
||
<el-button type="primary" class="export-btn" @click="handleExport">导出</el-button>
|
||
</template>
|
||
<template slot="itemState" slot-scope="{ data }">
|
||
<el-switch
|
||
v-model="data.itemState"
|
||
:active-value="'0'"
|
||
:inactive-value="'1'"
|
||
@change="handleStateChange(data)"
|
||
/>
|
||
</template>
|
||
<template slot="handle" slot-scope="{ data }">
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['enterpriseLibrary:rejectionItem:edit']"
|
||
class="action-btn"
|
||
style="color: #EAA819;"
|
||
@click="handleUpdate(data)"
|
||
>
|
||
编辑
|
||
</el-button>
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['enterpriseLibrary:rejectionItem:del']"
|
||
class="action-btn"
|
||
style="color: #DB3E29;"
|
||
@click="handleDelete(data)"
|
||
>
|
||
删除
|
||
</el-button>
|
||
</template>
|
||
</TableModel>
|
||
</div>
|
||
|
||
<!-- 新增/编辑废标项弹窗 -->
|
||
<RejectionItemForm
|
||
ref="rejectionItemForm"
|
||
v-if="dialogVisible"
|
||
:isAdd="isAdd"
|
||
:rowData="row"
|
||
@handleQuery="handleQuery"
|
||
@closeDialog="dialogVisible = false"
|
||
:title="dialogTitle"
|
||
:width="600"
|
||
/>
|
||
|
||
<!-- 导入弹窗 -->
|
||
<el-dialog
|
||
title="导入废标项"
|
||
:visible.sync="importDialogVisible"
|
||
width="500px"
|
||
:close-on-click-modal="false"
|
||
>
|
||
<el-upload
|
||
class="upload-excel"
|
||
ref="upload"
|
||
action
|
||
:http-request="handleFileUpload"
|
||
:on-success="onUploadSuccess"
|
||
:on-error="onUploadError"
|
||
:before-upload="beforeUpload"
|
||
:show-file-list="true"
|
||
accept=".xlsx, .xls"
|
||
:limit="1"
|
||
:file-list="fileList"
|
||
>
|
||
<el-button size="small" type="primary">选择Excel文件</el-button>
|
||
<div slot="tip" class="el-upload__tip">
|
||
仅支持.xlsx、.xls格式文件,<el-button type="text" @click="downloadTemplate">下载导入模板</el-button>
|
||
</div>
|
||
</el-upload>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button @click="importDialogVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="submitImport">确认导入</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</el-card>
|
||
</template>
|
||
|
||
<script>
|
||
import TableModel from '@/components/TableModel2'
|
||
import { columnsList, formLabel } from './config'
|
||
import RejectionItemForm from './components/RejectionItemForm.vue'
|
||
import {
|
||
importRejectionItem,
|
||
downloadImportTemplate,
|
||
listRejectionItem,
|
||
delRejectionItem,
|
||
updateRejectionItem,
|
||
checkItemNameUnique,
|
||
exportRejectionItem // 导入导出接口
|
||
} from '@/api/enterpriseLibrary/rejectionItem/rejectionItem'
|
||
import { encryptWithSM4, decryptWithSM4 } from '@/utils/sm'
|
||
|
||
export default {
|
||
name: 'RejectionItem',
|
||
components: {
|
||
TableModel,
|
||
RejectionItemForm
|
||
},
|
||
data() {
|
||
return {
|
||
formLabel,
|
||
columnsList,
|
||
listRejectionItem, // 列表查询接口
|
||
dialogVisible: false,
|
||
isAdd: '',
|
||
row: {},
|
||
dialogTitle: '',
|
||
enterpriseId: decryptWithSM4(this.$route.query.enterpriseId) || '0',
|
||
importDialogVisible: false, // 导入弹窗开关
|
||
fileList: [], // 上传的文件列表
|
||
uploadFile: null // 暂存上传的文件对象
|
||
}
|
||
},
|
||
created() {
|
||
// 初始化企业ID到TableModel的查询参数中
|
||
this.$nextTick(() => {
|
||
this.$refs.rejectionItemTableRef.queryParams.enterpriseId = this.enterpriseId
|
||
this.$refs.rejectionItemTableRef.getTableList()
|
||
})
|
||
},
|
||
methods: {
|
||
// 返回上一页
|
||
handleBack() {
|
||
const obj = {
|
||
path: "/enterpriseKnowledge/index",
|
||
query: {
|
||
enterpriseId: encryptWithSM4(this.$refs.rejectionItemTableRef.queryParams.enterpriseId || '0'),
|
||
}
|
||
}
|
||
this.$tab.closeOpenPage(obj)
|
||
},
|
||
// 新增废标项
|
||
handleAdd() {
|
||
this.dialogTitle = "新增废标项";
|
||
this.isAdd = 'add';
|
||
this.row = {
|
||
enterpriseId: this.$refs.rejectionItemTableRef.queryParams.enterpriseId
|
||
}; // 携带企业ID
|
||
this.dialogVisible = true;
|
||
},
|
||
// 修改废标项
|
||
handleUpdate(row) {
|
||
this.dialogTitle = "修改废标项";
|
||
this.isAdd = 'edit';
|
||
this.row = { ...row };
|
||
this.dialogVisible = true;
|
||
},
|
||
// 切换状态(启用/未启用)
|
||
handleStateChange(row) {
|
||
// 保存当前状态(用于更新失败时回滚)
|
||
const originalState = row.itemState;
|
||
|
||
// 调用更新接口
|
||
updateRejectionItem({
|
||
...row,
|
||
itemState: row.itemState
|
||
}).then(res => {
|
||
if (res.code === 200) {
|
||
this.$modal.msgSuccess("状态更新成功");
|
||
// 状态更新成功后,调用列表接口刷新数据
|
||
this.handleQuery();
|
||
} else {
|
||
this.$modal.msgError(res.msg);
|
||
// 更新失败时回滚开关状态
|
||
row.itemState = originalState;
|
||
}
|
||
}).catch(error => {
|
||
this.$modal.msgError("状态更新失败:" + error);
|
||
// 接口调用失败时回滚开关状态
|
||
row.itemState = originalState;
|
||
});
|
||
},
|
||
// 删除废标项
|
||
handleDelete(row) {
|
||
this.$modal.confirm(`是否确认删除“${row.itemName}”?`).then(() => {
|
||
this.$modal.loading("正在删除,请稍候...");
|
||
delRejectionItem({
|
||
itemId: row.itemId,
|
||
enterpriseId: this.$refs.rejectionItemTableRef.queryParams.enterpriseId
|
||
}).then(res => {
|
||
this.$modal.closeLoading();
|
||
if (res.code === 200) {
|
||
this.$modal.msgSuccess("删除成功");
|
||
this.handleQuery();
|
||
} else {
|
||
this.$modal.msgError(res.msg);
|
||
}
|
||
}).catch(error => {
|
||
this.$modal.closeLoading();
|
||
this.$modal.msgError(error);
|
||
});
|
||
});
|
||
},
|
||
// 查询列表(调用TableModel的内置方法)
|
||
handleQuery() {
|
||
this.$refs.rejectionItemTableRef.getTableList();
|
||
},
|
||
|
||
// 导出废标项(核心修改:实现导出逻辑)
|
||
handleExport() {
|
||
// 1. 获取表格的查询参数(包含企业ID和用户输入的筛选条件)
|
||
const queryParams = {
|
||
...this.$refs.rejectionItemTableRef.queryParams,
|
||
enterpriseId: this.enterpriseId // 确保携带企业ID
|
||
};
|
||
|
||
// 2. 显示加载中提示
|
||
this.$modal.loading("正在导出数据,请稍候...");
|
||
|
||
// 3. 调用导出接口
|
||
exportRejectionItem(queryParams)
|
||
.then(blob => {
|
||
this.$modal.closeLoading();
|
||
|
||
// 4. 处理文件流,生成下载链接
|
||
const url = window.URL.createObjectURL(new Blob([blob]));
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
// 文件名格式:废标项数据_时间戳.xlsx
|
||
a.download = `废标项数据_${new Date().getTime()}.xlsx`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
|
||
// 5. 清理资源
|
||
window.URL.revokeObjectURL(url);
|
||
document.body.removeChild(a);
|
||
|
||
// 6. 提示导出成功
|
||
this.$modal.msgSuccess("导出成功");
|
||
})
|
||
.catch(error => {
|
||
this.$modal.closeLoading();
|
||
// 错误处理
|
||
this.$modal.msgError(`导出失败:${error.message || error}`);
|
||
});
|
||
},
|
||
// 打开导入弹窗
|
||
handleImport() {
|
||
this.importDialogVisible = true;
|
||
this.fileList = []; // 清空文件列表
|
||
this.uploadFile = null;
|
||
},
|
||
|
||
// 上传前校验文件格式和大小
|
||
beforeUpload(file) {
|
||
const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||
|| file.type === 'application/vnd.ms-excel';
|
||
const isLt2M = file.size / 1024 / 1024 < 2; // 限制2MB以内
|
||
|
||
if (!isExcel) {
|
||
this.$message.error('只能上传Excel文件!');
|
||
return false;
|
||
}
|
||
if (!isLt2M) {
|
||
this.$message.error('文件大小不能超过2MB!');
|
||
return false;
|
||
}
|
||
|
||
// 暂存文件对象,用于后续手动提交
|
||
this.uploadFile = file;
|
||
return false; // 阻止自动上传,等待用户点击"确认导入"
|
||
},
|
||
|
||
// 自定义文件上传(实际调用后端导入接口)
|
||
handleFileUpload(options) {
|
||
const formData = new FormData();
|
||
// 必传:企业ID(确保数据归属)
|
||
formData.append('enterpriseId', this.enterpriseId);
|
||
// 必传:Excel文件
|
||
formData.append('file', options.file);
|
||
|
||
// 调用后端导入接口
|
||
importRejectionItem(formData)
|
||
.then(res => {
|
||
options.onSuccess(res); // 触发上传成功回调
|
||
})
|
||
.catch(err => {
|
||
options.onError(err); // 触发上传失败回调
|
||
});
|
||
},
|
||
|
||
// 点击"确认导入"按钮
|
||
submitImport() {
|
||
if (!this.uploadFile) {
|
||
this.$message.warning('请选择要导入的Excel文件');
|
||
return;
|
||
}
|
||
// 手动触发上传
|
||
this.$refs.upload.submit();
|
||
},
|
||
|
||
// 上传成功回调
|
||
onUploadSuccess(res) {
|
||
if (res.code === 200) {
|
||
this.$message.success(`导入成功!共${res.successCount}条,失败${res.failCount}条`);
|
||
// 关闭弹窗并刷新列表
|
||
this.importDialogVisible = false;
|
||
this.handleQuery(); // 刷新数据列表
|
||
} else {
|
||
this.$message.error(`导入失败:${res.msg || '服务器异常'}`);
|
||
// 若有失败数据,可展示失败原因
|
||
if (res.failData && res.failData.length > 0) {
|
||
console.log('导入失败详情:', res.failData);
|
||
// 可弹窗展示失败数据明细
|
||
}
|
||
}
|
||
},
|
||
|
||
// 上传失败回调
|
||
onUploadError(err) {
|
||
this.$message.error(`导入异常:${err.message || '网络错误'}`);
|
||
},
|
||
|
||
// 下载导入模板
|
||
downloadTemplate() {
|
||
downloadImportTemplate(this.enterpriseId)
|
||
.then(blob => {
|
||
// 处理模板文件流,触发下载
|
||
const url = window.URL.createObjectURL(new Blob([blob]));
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `废标项导入模板.xlsx`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
window.URL.revokeObjectURL(url);
|
||
document.body.removeChild(a);
|
||
})
|
||
.catch(err => {
|
||
this.$message.error(`模板下载失败:${err.message}`);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
/* 原有样式不变 */
|
||
.rejection-item-container {
|
||
height: calc(100vh - 84px);
|
||
overflow: hidden;
|
||
//background: linear-gradient(180deg, #F1F6FF 20%, #E5EFFF 100%);
|
||
}
|
||
|
||
.back-container {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding: 0 20px;
|
||
|
||
.back-btn {
|
||
width: 98px;
|
||
height: 36px;
|
||
background: #FFFFFF;
|
||
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
|
||
border-radius: 4px;
|
||
border: none;
|
||
color: #666;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
background: #f5f5f5;
|
||
color: #409EFF;
|
||
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-btn {
|
||
width: 121px;
|
||
height: 36px;
|
||
background: #1F72EA;
|
||
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
|
||
border-radius: 4px;
|
||
border: none;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
transition: all 0.3s;
|
||
margin-right: 10px;
|
||
|
||
&:hover {
|
||
background: #4A8BFF;
|
||
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
|
||
}
|
||
}
|
||
|
||
.import-btn, .export-btn {
|
||
width: 98px;
|
||
height: 36px;
|
||
background: #1F72EA;
|
||
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
|
||
border-radius: 4px;
|
||
border: none;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
transition: all 0.3s;
|
||
margin-right: 10px;
|
||
|
||
&:hover {
|
||
background: #4A8BFF;
|
||
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
|
||
}
|
||
}
|
||
|
||
.action-btn {
|
||
margin-right: 8px;
|
||
|
||
&:last-child {
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
|
||
.upload-excel {
|
||
margin: 20px 0;
|
||
}
|
||
</style>
|