smart-bid-web/src/views/enterpriseLibrary/rejectionItem/index.vue

452 lines
13 KiB
Vue
Raw Normal View History

<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;
2025-11-05 14:16:09 +08:00
//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>