<template>
|
<div class="app-container product-view">
|
<div class="main-content">
|
<div class="search-section">
|
<el-form :inline="true" :model="queryForm" class="search-form">
|
<el-form-item label="产品名称">
|
<el-input
|
v-model="queryForm.productName"
|
placeholder="请输入产品名称"
|
clearable
|
style="width: 200px"
|
@keyup.enter="handleSearch"
|
/>
|
</el-form-item>
|
<el-form-item label="图纸编号">
|
<el-input
|
v-model="queryForm.model"
|
placeholder="请输入图纸编号"
|
clearable
|
style="width: 200px"
|
@keyup.enter="handleSearch"
|
/>
|
</el-form-item>
|
<el-form-item label="产品属性">
|
<el-select
|
v-model="queryForm.productType"
|
placeholder="请选择产品属性"
|
clearable
|
style="width: 150px"
|
>
|
<el-option label="自制" :value="1" />
|
<el-option label="外购" :value="2" />
|
<el-option label="委外" :value="3" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleSearch" icon="Search">
|
搜索
|
</el-button>
|
<el-button @click="handleReset" icon="Refresh">
|
重置
|
</el-button>
|
</el-form-item>
|
</el-form>
|
<div class="action-buttons">
|
<el-button type="primary" @click="openModelDia('add')" icon="Plus">
|
新增产品
|
</el-button>
|
<el-button type="success" @click="handleImport" icon="Upload">
|
导入
|
</el-button>
|
<el-button type="danger" @click="handleDelete" icon="Delete" plain>
|
删除
|
</el-button>
|
</div>
|
</div>
|
|
<PIMTable
|
rowKey="id"
|
:column="tableColumn"
|
:tableData="tableData"
|
:page="page"
|
:isSelection="true"
|
@selection-change="handleSelectionChange"
|
:tableLoading="tableLoading"
|
@pagination="pagination"
|
></PIMTable>
|
</div>
|
|
<FormDialog
|
v-model="modelDia"
|
title="产品信息"
|
width="500px"
|
@close="closeModelDia"
|
@confirm="submitModelForm"
|
>
|
<el-form
|
:model="modelForm"
|
label-width="100px"
|
:rules="modelRules"
|
ref="modelFormRef"
|
>
|
<el-form-item label="产品名称" prop="productName">
|
<el-input
|
v-model="modelForm.productName"
|
placeholder="请输入产品名称"
|
clearable
|
maxlength="50"
|
show-word-limit
|
/>
|
</el-form-item>
|
<el-form-item label="图纸编号" prop="model">
|
<el-input
|
v-model="modelForm.model"
|
placeholder="请输入图纸编号"
|
clearable
|
/>
|
</el-form-item>
|
<el-form-item label="规格型号" prop="drawingNumber">
|
<el-input
|
v-model="modelForm.drawingNumber"
|
placeholder="请输入规格型号"
|
clearable
|
/>
|
</el-form-item>
|
<el-form-item label="单位" prop="unit">
|
<el-input
|
v-model="modelForm.unit"
|
placeholder="请输入单位"
|
clearable
|
/>
|
</el-form-item>
|
<el-form-item label="产品属性" prop="productType">
|
<el-select
|
v-model="modelForm.productType"
|
placeholder="请选择产品属性"
|
clearable
|
style="width: 100%"
|
>
|
<el-option label="自制" :value="1" />
|
<el-option label="外购" :value="2" />
|
<el-option label="委外" :value="3" />
|
</el-select>
|
</el-form-item>
|
</el-form>
|
</FormDialog>
|
|
<FormDialog
|
v-model="importDia"
|
title="产品导入"
|
width="600px"
|
@cancel="importDia = false"
|
@confirm="submitImport"
|
>
|
<el-upload
|
ref="importUploadRef"
|
:limit="1"
|
accept=".xlsx,.xls"
|
:action="importUpload.url"
|
:headers="importUpload.headers"
|
:before-upload="importUpload.beforeUpload"
|
:on-success="importUpload.onSuccess"
|
:on-error="importUpload.onError"
|
:on-progress="importUpload.onProgress"
|
:on-change="importUpload.onChange"
|
:auto-upload="false"
|
drag
|
>
|
<i class="el-icon-upload"></i>
|
<div class="el-upload__text">
|
将文件拖到此处,或<em>点击上传</em>
|
</div>
|
<template #tip>
|
<div class="el-upload__tip">
|
仅支持 xls/xlsx,大小不超过 10MB。
|
<el-button link type="primary" @click="importTemplate">下载导入模板</el-button>
|
</div>
|
</template>
|
</el-upload>
|
</FormDialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive } from "vue";
|
import { ElMessageBox } from "element-plus";
|
import { getToken } from "@/utils/auth.js";
|
import { FileUpload } from "@/components/Upload";
|
import FormDialog from "@/components/Dialog/FormDialog.vue";
|
import {
|
addOrEditProductModel,
|
delProduct,
|
productListPage,
|
downloadTemplate,
|
} from "@/api/basicData/product.js";
|
import ImportExcel from "./ImportExcel/index.vue";
|
|
const { proxy } = getCurrentInstance();
|
const importUploadRef = ref(null);
|
|
const modelDia = ref(false);
|
const importDia = ref(false);
|
const modelOperationType = ref("");
|
const tableData = ref([]);
|
const tableLoading = ref(false);
|
const selectedRows = ref([]);
|
const modelFormRef = ref();
|
|
const queryForm = reactive({
|
productName: "",
|
model: "",
|
productType: null,
|
});
|
|
const page = reactive({
|
current: 1,
|
size: 50,
|
total: 0,
|
});
|
|
const tableColumn = ref([
|
{
|
label: "产品名称",
|
prop: "productName",
|
minWidth: 200,
|
},
|
{
|
label: "图纸编号",
|
prop: "model",
|
minWidth: 150,
|
},
|
{
|
label: "规格型号",
|
prop: "drawingNumber",
|
minWidth: 150,
|
},
|
{
|
label: "单位",
|
prop: "unit",
|
minWidth: 100,
|
},
|
{
|
label: "产品属性",
|
prop: "productType",
|
width: 100,
|
dataType: "tag",
|
formatData: (v) => ({ "1": "自制", "2": "外购", "3": "委外" }[String(v)] ?? v),
|
formatType: (v) => {
|
const typeMap = { "1": "success", "2": "warning", "3": "info" };
|
return typeMap[String(v)] || "info";
|
},
|
},
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
width: 100,
|
operation: [
|
{
|
name: "编辑",
|
type: "text",
|
clickFun: (row) => {
|
openModelDia("edit", row);
|
},
|
},
|
],
|
},
|
]);
|
|
const data = reactive({
|
modelForm: {
|
productName: "",
|
model: "",
|
unit: "",
|
drawingNumber: "",
|
productType: null,
|
},
|
modelRules: {
|
productName: [
|
{ required: true, message: "请输入产品名称", trigger: "blur" },
|
{ max: 50, message: "产品名称不能超过50个字符", trigger: "blur" },
|
],
|
model: [{ required: true, message: "请输入图纸编号", trigger: "blur" }],
|
unit: [{ required: true, message: "请输入单位", trigger: "blur" }],
|
drawingNumber: [],
|
productType: [{ required: true, message: "请选择产品属性", trigger: "change" }],
|
},
|
});
|
const { modelForm, modelRules } = toRefs(data);
|
|
const importUpload = reactive({
|
title: "产品导入",
|
open: false,
|
url: import.meta.env.VITE_APP_BASE_API + "/basic/product/import",
|
headers: { Authorization: "Bearer " + getToken() },
|
isUploading: false,
|
beforeUpload: (file) => {
|
const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
|
const isLt10M = file.size / 1024 / 1024 < 10;
|
if (!isExcel) {
|
proxy.$modal.msgError("上传文件只能是 xlsx/xls 格式!");
|
return false;
|
}
|
if (!isLt10M) {
|
proxy.$modal.msgError("上传文件大小不能超过 10MB!");
|
return false;
|
}
|
return true;
|
},
|
onChange: (file, fileList) => {
|
console.log('文件状态改变', file, fileList);
|
},
|
onProgress: (event, file, fileList) => {
|
console.log('上传中...', event.percent);
|
},
|
onSuccess: (response, file, fileList) => {
|
console.log('上传成功', response, file, fileList);
|
importUpload.isUploading = false;
|
if (response.code === 200) {
|
proxy.$modal.msgSuccess("导入成功");
|
importDia.value = false;
|
if (importUploadRef.value) {
|
importUploadRef.value.clearFiles();
|
}
|
getModelList();
|
} else {
|
proxy.$modal.msgError(response.msg || "导入失败");
|
}
|
},
|
onError: (error, file, fileList) => {
|
console.log('上传失败', error, file, fileList);
|
importUpload.isUploading = false;
|
proxy.$modal.msgError("导入失败");
|
}
|
});
|
|
const handleSearch = () => {
|
page.current = 1;
|
getModelList();
|
};
|
|
const handleReset = () => {
|
queryForm.productName = "";
|
queryForm.model = "";
|
queryForm.productType = null;
|
page.current = 1;
|
getModelList();
|
};
|
|
const openModelDia = (type, data) => {
|
modelOperationType.value = type;
|
modelDia.value = true;
|
modelForm.value.productName = "";
|
modelForm.value.model = "";
|
modelForm.value.id = "";
|
modelForm.value.unit = "";
|
modelForm.value.drawingNumber = "";
|
modelForm.value.productType = null;
|
if (type === "edit") {
|
modelForm.value = { ...data };
|
}
|
};
|
|
const submitModelForm = () => {
|
modelFormRef.value.validate((valid) => {
|
if (valid) {
|
addOrEditProductModel(modelForm.value).then((res) => {
|
proxy.$modal.msgSuccess("提交成功");
|
closeModelDia();
|
getModelList();
|
});
|
}
|
});
|
};
|
|
const closeModelDia = () => {
|
modelFormRef.value.resetFields();
|
modelDia.value = false;
|
};
|
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection;
|
};
|
|
const pagination = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getModelList();
|
};
|
|
const getModelList = () => {
|
tableLoading.value = true;
|
productListPage({
|
productName: queryForm.productName.trim(),
|
model: queryForm.model.trim(),
|
productType: queryForm.productType,
|
current: page.current,
|
size: page.size,
|
}).then((res) => {
|
tableData.value = res.data.records;
|
page.total = res.data.total;
|
tableLoading.value = false;
|
}).catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
const handleDelete = () => {
|
let ids = [];
|
if (selectedRows.value.length > 0) {
|
ids = selectedRows.value.map((item) => item.id);
|
} else {
|
proxy.$modal.msgWarning("请选择数据");
|
return;
|
}
|
ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
tableLoading.value = true;
|
delProduct(ids)
|
.then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
getModelList();
|
})
|
.finally(() => {
|
tableLoading.value = false;
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
const handleImport = () => {
|
importDia.value = true;
|
if (importUploadRef.value) {
|
importUploadRef.value.clearFiles();
|
}
|
};
|
|
const submitImport = () => {
|
importUploadRef.value.submit();
|
};
|
|
const importTemplate = () => {
|
proxy.download("/basic/product/downloadTemplate", {}, "产品导入模板.xlsx");
|
};
|
|
getModelList();
|
</script>
|
|
<style scoped>
|
.product-view {
|
padding: 20px;
|
background: #f5f7fa;
|
min-height: 100vh;
|
}
|
|
.main-content {
|
background: #ffffff;
|
border-radius: 8px;
|
padding: 24px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
}
|
|
.search-section {
|
margin-bottom: 20px;
|
padding-bottom: 20px;
|
border-bottom: 1px solid #e4e7ed;
|
}
|
|
.search-form {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 12px;
|
align-items: center;
|
}
|
|
.search-form :deep(.el-form-item) {
|
margin-bottom: 12px;
|
}
|
|
.action-buttons {
|
display: flex;
|
gap: 10px;
|
margin-top: 16px;
|
}
|
|
:deep(.el-dialog__body) {
|
padding: 20px 24px;
|
}
|
|
:deep(.el-form-item__label) {
|
font-weight: 500;
|
color: #303133;
|
}
|
|
:deep(.el-input__inner) {
|
border-radius: 4px;
|
}
|
|
:deep(.el-button) {
|
border-radius: 4px;
|
font-weight: 500;
|
}
|
|
:deep(.el-upload-dragger) {
|
border-radius: 8px;
|
border: 2px dashed #dcdfe6;
|
transition: all 0.3s;
|
}
|
|
:deep(.el-upload-dragger:hover) {
|
border-color: #409eff;
|
background-color: #f5f7fa;
|
}
|
</style>
|