bonus-ui/src/views/canteen/superstore/shopMaterial/index.vue

784 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 类型管理 -->
<div class="app-container" id="toolsType">
<el-row :gutter="20">
<!--树数据-->
<el-col :span="5" :xs="24">
<div class="head-container">
商品类别
<el-input
v-model="keyWord"
placeholder="请输入关键字进行搜索"
clearable
maxlength="50"
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
</div>
<div class="head-container">
<el-tree
style="height: 700px; overflow: scroll"
:data="treeOptions"
:props="defaultProps"
:show-checkbox="true"
:default-expand-all="true"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="typeTree"
node-key="id"
highlight-current
@node-click="handleNodeClick"
@check-change="handleCheckChange"
>
<span class="custom-tree-node" slot-scope="{ node, data }" @mousemove="onMousemove(data)" @mouseleave="onMouseleave()">
<span v-if="isMousemoveId === data.id && node.label.length > 5">{{
node.label.slice(0, 5) + "..."
}}</span>
<span v-else>{{ node.label }}</span>
<span class="btn-items" v-if="isMousemoveId === data.id">
<el-button
type="text"
size="mini"
icon="el-icon-plus" v-if="data.level<1"
@click.stop="() => appendTreeNode(data)"
>
</el-button>
<el-button
type="text"
size="mini"
icon="el-icon-edit-outline"
style="color: #67c23a"
v-if="data.id !== 0"
@click.stop="() => editTreeNode(data)"
>
</el-button>
<el-button
type="text"
size="mini"
icon="el-icon-delete"
style="color: #f56c6c"
v-if="data.parentId != '0'"
@click.stop="() => removeTreeNode(data)"
>
</el-button>
</span>
</span>
</el-tree>
</div>
</el-col>
<!--用户数据-->
<el-col :span="19" :xs="24">
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="所属区域" prop="areaId">
<el-cascader v-model="queryParams.areaId"
:options="treeAreaOptions" :filterable="true" style="width: 100%;" :show-all-levels="false"
:props="{
emitPath: false,// 若设置 false则只返回该节点的值只返回最后选择的id
checkStrictly: false,//来设置父子节点取消选中关联,从而达到选择任意一级选项的目的
value:'id',label:'label'
}" clearable>
</el-cascader>
</el-form-item>
<el-form-item label="商品编码" prop="materialCode">
<el-input
v-model="queryParams.materialCode"
placeholder="请输入商品编码"
clearable maxlength="30"
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="商品名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入商品名称"
clearable maxlength="30"
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="条码" prop="barCode">
<el-input
v-model="queryParams.barCode"
placeholder="请输入条码"
clearable maxlength="30"
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>查询</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
size="mini"
:disabled="multiple"
@click="handleBatchDel"
>批量删除</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url"
:show-file-list="false"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
>
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
>批量导入
</el-button>
</el-upload>
</el-col>
<el-col :span="1.5">
<el-button
size="mini"
@click="importTemplate"
>模板下载
</el-button>
</el-col> -->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="tableList" height="550" ref="multipleTable" border :row-key="(row)=>{return row.materialId}" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" :reserve-selection="true"/>
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column label="商品编码" align="center" key="materialCode" prop="materialCode" :show-overflow-tooltip="true" />
<el-table-column label="商品名称" align="center" key="materialName" prop="materialName" :show-overflow-tooltip="true" />
<el-table-column label="所属区域" align="center" key="areaName" prop="areaName" :show-overflow-tooltip="true" />
<el-table-column label="商品类别" align="center" key="materialTypeName" prop="materialTypeName" :show-overflow-tooltip="true" />
<el-table-column label="单位" align="center" key="unitName" prop="unitName" :show-overflow-tooltip="true" width="100"/>
<el-table-column label="条码" align="center" key="barCode" prop="barCode" :show-overflow-tooltip="true" />
<el-table-column label="商品进价(元)" align="center" key="unitPrice" prop="unitPrice" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ (scope.row.unitPrice/100).toFixed(2)||"" }}</span>
</template>
</el-table-column>
<el-table-column label="零售价(元)" align="center" key="salePrice" prop="salePrice" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ (scope.row.salePrice/100).toFixed(2)||"" }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100" fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleUpdate(scope.row)"
>
编辑
</el-button>
<el-button
size="mini"
type="text" style="color: red;"
@click="handleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
<!-- 添加或修改商品类别对话框 -->
<el-dialog
:title="title+'-商品类别'"
:visible.sync="open"
width="600px"
append-to-body
:close-on-click-modal="false"
>
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
<el-form-item label="所属区域" prop="areaId">
<el-cascader v-model="form.areaId" :disabled="isEditType"
:options="treeAreaOptions" :filterable="true" style="width: 100%;" :show-all-levels="false"
:props="{
emitPath: false,// 若设置 false则只返回该节点的值只返回最后选择的id
checkStrictly: false,//来设置父子节点取消选中关联,从而达到选择任意一级选项的目的
value:'id',label:'label'
}" clearable>
</el-cascader>
</el-form-item>
<el-row>
<el-col :span="24">
<el-form-item label="商品类别" prop="materialTypeName">
<el-input
v-model="form.materialTypeName"
placeholder="请输入商品类别"
maxlength="30"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSubmit">确 定</el-button>
<el-button @click="open=false"> </el-button>
</div>
</el-dialog>
<!-- 添加或修改用户配置对话框 -->
<material-dialog :visible.sync="dialogVisible" :title="title" :treeOptions="treeOptions" :treeAreaOptions="treeAreaOptions" @submit="handleDialogSubmit" ref="materialDialog" />
</div>
</template>
<script>
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import { systemAreaTreeApi } from "@/api/base/area";
import { shopMaterialTreeApi,addMaterialTypeApi,updateMaterialTypeApi,removeMaterialTypeApi} from "@/api/superStore/shopMaterial";
import { getMaterialListApi,addMaterialApi, updateMaterialApi, removeMaterialApi,batchRemoveMaterialApi} from "@/api/superStore/shopMaterial";
import MaterialDialog from './components/MaterialDialog.vue';
import { getToken } from '@/utils/auth';
import { downloadFileByUrl } from '@/utils/download'
export default {
name: "Material",
components: {
Treeselect,
MaterialDialog
},
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 树选项
treeOptions: undefined,
treeTemp: [],
isMousemoveId: null,
defaultProps: {
children: "children",
label: "categoryName",
},
keyWord:"",//左侧树-关键字查询
isEditType:false,//是否编辑
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
areaId:null,
materialName:"",
barCode:"",
materialCode:"",
materialTypeIds:[]
},
// 总条数
total: 0,
//列表数据
tableList: undefined,
// 是否显示弹出层
open: false,
dialogVisible: false,
// 弹出层标题
title: "",
// 表单参数
form: {
materialTypeName: "",
parentId: "",
areaId:null
},
// 表单校验
rules: {
materialTypeName: [
{
required: true,
message: "类别名称不能为空",
trigger: "blur",
},
]
},
parentId: undefined,
treeAreaOptions:[],//区域树
batchIds:[],
//导入参数
upload: {
// 是否禁用上传
isUploading: false,
// 设置上传的请求头部
headers: { Authorization: 'Bearer ' + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + '/smart-canteen/api/v1/menumaterial/batch/import/material-product',
},
};
},
watch: {
// 根据名称筛选部门树
keyWord(val) {
this.$refs.typeTree.filter(val);
},
},
created() {
this.getTreeData();
this.getAreaTreeData();
},
methods: {
// 筛选节点 - 左侧树
filterNode(value, data) {
if (!value) return true;
return data.categoryName.indexOf(value) !== -1;
},
/** 查询新增页面-上级类型下拉树结构 */
getTreeData() {
let param = {
goodsType:2
}
shopMaterialTreeApi(param).then((response) => {
this.treeOptions = response.data;
this.addLevel(this.treeOptions)
console.log("this.treeOptions",this.treeOptions)
if(this.treeOptions && this.treeOptions.length > 0){
this.getList();
} else {
this.getList();
}
});
},
handleTree(data, idKey, parentIdKey = 'parentId', childrenKey = 'children') {
// 用于存储节点数据的Map以idKey为键
const nodeMap = new Map();
// 用于存储根节点的数组
const rootNodes = [];
// 遍历数据构建nodeMap并找到根节点
data.forEach(node => {
// 将节点添加到nodeMap中并初始化children为空数组
nodeMap.set(node[idKey], { ...node, [childrenKey]: [] });
// 如果parentId为null或父节点不存在于nodeMap中则该节点为根节点
if (node[parentIdKey] === null || !nodeMap.has(node[parentIdKey])) {
// 将根节点添加到rootNodes数组中
rootNodes.push(nodeMap.get(node[idKey]));
} else {
// 否则将当前节点添加到其父节点的children列表中
// 获取父节点
const parentNode = nodeMap.get(node[parentIdKey]);
// 将当前节点添加到父节点的children列表中
parentNode[childrenKey].push(nodeMap.get(node[idKey]));
}
});
// 返回根节点数组,它现在包含了完整的树形结构
return rootNodes;
},
addLevel(nodes, level = 0) {
nodes.forEach(node => {
node.level = level; // 设置当前节点的层级
if (node.children) { // 如果节点有子节点,递归处理子节点
this.addLevel(node.children, level + 1);
}
});
},
// 节点单击事件 - 左侧树
async handleNodeClick(data, node) {
console.log(data)
// this.handleQuery();
},
handleCheckChange(data, checked, indeterminate) {
this.handleQuery();
},
/* 树节点增加 */
appendTreeNode(data) {
console.log(data)
this.isEditType=false;
this.form={}
this.resetForm("form");
this.$set(this.form,"parentId",data.id)
this.$set(this.form,"goodsType",data.categoryType)
this.open = true;
this.title = "新增";
},
/* 树节点修改 */
editTreeNode(data) {
this.isEditType=true;
this.form={}
this.resetForm("form");
this.form = {
...data
};
this.$set(this.form,"materialTypeId",data.id)
this.$set(this.form,"materialTypeName",data.categoryName)
this.$set(this.form,"goodsType",data.categoryType)
this.open = true;
this.title = "修改";
},
/* 树节点删除 */
removeTreeNode(data) {
console.log(data, "删除时的数据源--");
this.$modal
.confirm("是否确认删除数据项?")
.then(function () {
return removeMaterialTypeApi({"id":data.id});
})
.then(() => {
this.$modal.msgSuccess("删除成功");
this.getList();
this.getTreeData();
})
.catch(() => {});
},
onMousemove(data) {
this.isMousemoveId = data.id;
},
onMouseleave() {
this.isMousemoveId = null;
},
/** 操作左侧树-表单提交 */
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
if (this.form.materialTypeId != undefined) {
updateMaterialTypeApi(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getTreeData();
});
} else {
console.log(this.form)
addMaterialTypeApi(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getTreeData();
});
}
}
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.queryParams.pageNum = 1;
this.queryParams.pageSize = 10;
this.handleQuery();
},
/** 查询列表 */
getList() {
console.log(this.$refs.typeTree.getCheckedKeys())
this.loading = true;
let params= {
"pageSize": this.queryParams.pageSize,
"pageNum": this.queryParams.pageNum,
"areaId": this.queryParams.areaId,
"materialName": this.queryParams.materialName,
"barCode": this.queryParams.barCode,
"materialCode": this.queryParams.materialCode,
"goodsType": 2,
"materialTypeIds": this.$refs.typeTree.getCheckedKeys(),
}
getMaterialListApi(params).then((response) => {
this.tableList = response.rows;
this.total = Number(response.total);
this.loading = false;
});
},
//新增修改弹窗-区域树
getAreaTreeData() {
systemAreaTreeApi({}).then((response) => {
this.treeAreaOptions = response.data;
});
},
/** 新增按钮操作 */
handleAdd() {
this.title = "新增";
this.dialogVisible = true;
},
/** 修改按钮操作 */
handleUpdate(row) {
this.title = "修改";
this.dialogVisible = true;
// 在显示对话框后,可以通过 $refs 访问子组件方法设置表单数据
this.$nextTick(() => {
// 假设子组件提供了 setFormData 方法
this.$refs.materialDialog.setFormData(row);
});
},
/** 处理对话框提交 */
handleDialogSubmit(formData) {
if (this.title === "新增") {
formData.goodsType=2
addMaterialApi(formData).then(response => {
this.$modal.msgSuccess("新增成功");
this.dialogVisible = false;
this.getList();
});
} else {
formData.goodsType=2
updateMaterialApi(formData).then(response => {
this.$modal.msgSuccess("修改成功");
this.dialogVisible = false;
this.getList();
});
}
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal
.confirm("是否确认删除数据项?")
.then(function () {
return removeMaterialApi({"materialId":row.materialId});
})
.then(() => {
this.$modal.msgSuccess("删除成功");
this.getList();
})
.catch(() => {});
},
handleSelectionChange(selection){
this.batchIds = []
this.batchIds = selection.map((item) => item.materialId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
// 批量删除
handleBatchDel(){
console.log(this.batchIds)
removeMaterialApi({"materialId":this.batchIds.join(",")}).then(response => {
this.$modal.msgSuccess("删除成功");
this.$refs.multipleTable.clearSelection()
this.getList();
});
},
//批量导入
// /api/v1/menumaterial/batch/import/material
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$modal.msgSuccess("后台导入中,请稍后刷新列表!");
this.getList()
},
/** 下载模板操作 */
importTemplate() {
let url = window.location.origin + '/glweb/template/批量新增商品模板.xlsx';
console.log(url)
downloadFileByUrl(url)
},
// getParentName(list, id) {
// try {
// list.forEach((e) => {
// if (e.id == id) {
// this.form.label = e.label;
// throw new Error();
// } else {
// if (e.children && e.children.length > 0) {
// this.getParentName(e.children, id);
// }
// }
// });
// } catch (error) {}
// },
},
};
</script>
<style lang="scss" scoped>
::v-deep.el-table .fixed-width .el-button--mini {
width: 60px !important;
margin-bottom: 10px;
}
::v-deep .btn-items .el-button + .el-button {
margin-left: 6px;
}
.btn-items {
margin-left: 4px;
.el-button--text {
font-size: 16px;
}
}
// ::v-deep .el-tree .el-tree-node__expand-icon.expanded {
// -webkit-transform: rotate(0deg);
// transform: rotate(0deg);
// }
// ::v-deep .el-tree .el-icon-caret-right:before {
// content: "\e783";
// font-size: 16px;
// }
// ::v-deep
// .el-tree
// .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
// content: "\e781";
// font-size: 16px;
// color: #1890ff;
// }
// ::v-deep .el-tree-node__content > .el-tree-node__expand-icon {
// color: #1890ff !important;
// }
// ::v-deep .el-tree-node__expand-icon.is-leaf {
// color: transparent !important;
// }
// ::v-deep
// .el-tree--highlight-current
// .el-tree-node.is-current
// > .el-tree-node__content {
// background-color: #8decf1;
// }
::v-deep .el-dialog .material-dialog {
// 表单标签文字样式
.el-form-item__label {
font-size: 14px;
color: #606266;
font-weight: 500;
line-height: 1.5;
}
// 输入框文字样式
.el-input__inner {
font-size: 14px;
color: #303133;
&::placeholder {
font-size: 13px;
color: #c0c4cc;
}
}
// 单位文字样式
span {
font-size: 14px;
// color: #606266;
margin-left: 8px;
}
// 下拉选择框文字样式
.el-select {
.el-input__inner {
font-size: 14px;
color: #303133;
}
}
// 只读输入框样式
.el-input.is-disabled .el-input__inner {
background-color: #f5f7fa;
border-color: #e4e7ed;
color: #606266;
cursor: not-allowed;
}
}
// 表格内文字样式
::v-deep .el-table {
font-size: 14px;
th {
font-weight: 500;
color: #303133;
}
td {
color: #606266;
}
}
// 按钮文字样式
::v-deep .el-button {
font-size: 14px;
&--text {
font-size: 13px;
}
}
// 树节点文字样式
::v-deep .el-tree-node__label {
font-size: 14px;
color: #606266;
}
// 搜索框文字样式
::v-deep .el-input--small {
.el-input__inner {
font-size: 13px;
&::placeholder {
font-size: 13px;
color: #c0c4cc;
}
}
}
</style>