删除根目录的node_modules
This commit is contained in:
44
gear-ui3/src/api/oa/bom.js
Normal file
44
gear-ui3/src/api/oa/bom.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询BOM 头,关联产品或原材料列表
|
||||||
|
export function listBom(query) {
|
||||||
|
return request({
|
||||||
|
url: '/klp/bom/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询BOM 头,关联产品或原材料详细
|
||||||
|
export function getBom(bomId) {
|
||||||
|
return request({
|
||||||
|
url: '/klp/bom/' + bomId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增BOM 头,关联产品或原材料
|
||||||
|
export function addBom(data) {
|
||||||
|
return request({
|
||||||
|
url: '/klp/bom',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改BOM 头,关联产品或原材料
|
||||||
|
export function updateBom(data) {
|
||||||
|
return request({
|
||||||
|
url: '/klp/bom',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除BOM 头,关联产品或原材料
|
||||||
|
export function delBom(bomId) {
|
||||||
|
return request({
|
||||||
|
url: '/klp/bom/' + bomId,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
44
gear-ui3/src/api/oa/bomItem.js
Normal file
44
gear-ui3/src/api/oa/bomItem.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询BOM 明细,存放属性–值列表
|
||||||
|
export function listBomItem(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/bomItem/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询BOM 明细,存放属性–值详细
|
||||||
|
export function getBomItem(itemId) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/bomItem/' + itemId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增BOM 明细,存放属性–值
|
||||||
|
export function addBomItem(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/bomItem',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改BOM 明细,存放属性–值
|
||||||
|
export function updateBomItem(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/bomItem',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除BOM 明细,存放属性–值
|
||||||
|
export function delBomItem(itemId) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/bomItem/' + itemId,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
44
gear-ui3/src/api/oa/product.js
Normal file
44
gear-ui3/src/api/oa/product.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询产品列表
|
||||||
|
export function listProduct(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/product/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询产品详细
|
||||||
|
export function getProduct(productId) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/product/' + productId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增产品
|
||||||
|
export function addProduct(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/product',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改产品
|
||||||
|
export function updateProduct(data) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/product',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除产品
|
||||||
|
export function delProduct(productId) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/product/' + productId,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
44
gear-ui3/src/api/oa/productCategory.js
Normal file
44
gear-ui3/src/api/oa/productCategory.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询产品分类树列表
|
||||||
|
export function listProductCategory(query) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/productCategory/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询产品分类树详细
|
||||||
|
export function getProductCategory(categoryId) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/productCategory/' + categoryId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增产品分类树
|
||||||
|
export function addProductCategory(data) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/productCategory',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改产品分类树
|
||||||
|
export function updateProductCategory(data) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/productCategory',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除产品分类树
|
||||||
|
export function delProductCategory(categoryId) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/productCategory/' + categoryId,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
83
gear-ui3/src/components/Renderer/BomInfo.vue
Normal file
83
gear-ui3/src/components/Renderer/BomInfo.vue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<el-descriptions :column="1" border v-if="bomInfo.length > 0">
|
||||||
|
<el-descriptions-item v-for="item in bomInfo" :key="item.attrKey" :label="item.attrKey">
|
||||||
|
{{ item.attrValue }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<div v-else>
|
||||||
|
<el-empty description="暂无BOM信息" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import useProductStore from '@/store/modules/product';
|
||||||
|
import { ElEmpty } from 'element-plus';
|
||||||
|
|
||||||
|
// 定义组件props
|
||||||
|
const props = defineProps({
|
||||||
|
bomId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
itemType: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
itemId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 状态管理
|
||||||
|
const productStore = useProductStore();
|
||||||
|
const bomInfo = ref([]);
|
||||||
|
|
||||||
|
// 获取BOM信息的方法
|
||||||
|
const getBomInfo = async () => {
|
||||||
|
const bomMap = productStore.bomMap;
|
||||||
|
|
||||||
|
if (!props.bomId && !props.itemType && !props.itemId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bomId = props.bomId;
|
||||||
|
if (!bomId) {
|
||||||
|
// 这里假设productMap是productStore中的属性
|
||||||
|
bomId = productStore.productMap?.[props.itemId]?.bomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bomId) {
|
||||||
|
bomInfo.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await productStore.getBomInfo(bomId);
|
||||||
|
bomInfo.value = info;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听属性变化
|
||||||
|
watch(
|
||||||
|
() => props.bomId,
|
||||||
|
() => getBomInfo(),
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.itemId,
|
||||||
|
() => getBomInfo(),
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bom-info {
|
||||||
|
cursor: pointer;
|
||||||
|
/* 溢出隐藏显示省略号 */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
84
gear-ui3/src/components/Renderer/BomInfoMini.vue
Normal file
84
gear-ui3/src/components/Renderer/BomInfoMini.vue
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="bomInfo.length > 0">
|
||||||
|
<el-tooltip :content="bomInfo.map(item => item.attrKey + ':' + item.attrValue).join(',')" class="bom-info"
|
||||||
|
placement="top">
|
||||||
|
<span>{{bomInfo.map(item => item.attrKey).join(',')}}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-empty description="暂无BOM信息" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import useProductStore from '@/store/modules/product';
|
||||||
|
import { ElEmpty } from 'element-plus';
|
||||||
|
|
||||||
|
// 定义组件props
|
||||||
|
const props = defineProps({
|
||||||
|
bomId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
itemType: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
itemId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 状态管理
|
||||||
|
const productStore = useProductStore();
|
||||||
|
const bomInfo = ref([]);
|
||||||
|
|
||||||
|
// 获取BOM信息的方法
|
||||||
|
const getBomInfo = async () => {
|
||||||
|
const bomMap = productStore.bomMap;
|
||||||
|
|
||||||
|
if (!props.bomId && !props.itemType && !props.itemId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bomId = props.bomId;
|
||||||
|
if (!bomId) {
|
||||||
|
// 这里假设productMap是productStore中的属性
|
||||||
|
bomId = productStore.productMap?.[props.itemId]?.bomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bomId) {
|
||||||
|
bomInfo.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await productStore.getBomInfo(bomId);
|
||||||
|
bomInfo.value = info;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听属性变化
|
||||||
|
watch(
|
||||||
|
() => props.bomId,
|
||||||
|
() => getBomInfo(),
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.itemId,
|
||||||
|
() => getBomInfo(),
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bom-info {
|
||||||
|
cursor: pointer;
|
||||||
|
/* 溢出隐藏显示省略号 */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
88
gear-ui3/src/components/Renderer/ProductInfo.vue
Normal file
88
gear-ui3/src/components/Renderer/ProductInfo.vue
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<span class="product-name" @click="clickHandle">
|
||||||
|
<slot name="default" :product="product">
|
||||||
|
{{ product && product.productName ? product.productName : '--' }}
|
||||||
|
</slot>
|
||||||
|
</span>
|
||||||
|
<el-dialog
|
||||||
|
:visible="showDetail"
|
||||||
|
@close="showDetail = false"
|
||||||
|
:title="product && product.productName ? product.productName : '--' "
|
||||||
|
width="500px"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<el-descriptions :column="1" border>
|
||||||
|
<el-descriptions-item label="产品ID">
|
||||||
|
{{ product.productId || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="产品名称">
|
||||||
|
{{ product.productName || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="产品编码">
|
||||||
|
{{ product.productCode || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<BomInfo :bomId="product.bomId" />
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
import BomInfo from './BomInfo.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ProductInfo',
|
||||||
|
components: {
|
||||||
|
BomInfo
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
productId: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showDetail: false,
|
||||||
|
product: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
productMap: state => state.category.productMap
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clickHandle() {
|
||||||
|
this.showDetail = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
productId: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (!newVal) {
|
||||||
|
this.product = {};
|
||||||
|
}
|
||||||
|
const res = this.productMap[this.productId] ? this.productMap[this.productId] : {};
|
||||||
|
this.product = res;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.product-name {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 可选:调整描述列表的外边距 */
|
||||||
|
:deep(.el-descriptions) {
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
41
gear-ui3/src/store/modules/product.js
Normal file
41
gear-ui3/src/store/modules/product.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { listProduct } from '@/api/oa/product';
|
||||||
|
import { listBomItem } from '@/api/oa/bomItem';
|
||||||
|
|
||||||
|
const useProductStore = defineStore('product', {
|
||||||
|
state: () => ({
|
||||||
|
productMap: {},
|
||||||
|
bomMap: {},
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setProductMap(productMap) {
|
||||||
|
this.productMap = productMap;
|
||||||
|
},
|
||||||
|
setBomMap(bomMap) {
|
||||||
|
this.bomMap = bomMap;
|
||||||
|
},
|
||||||
|
async getBomInfo(bomId) {
|
||||||
|
try {
|
||||||
|
if (!this.bomMap[bomId]) {
|
||||||
|
const res = await listBomItem({ bomId });
|
||||||
|
this.bomMap[bomId] = res.rows;
|
||||||
|
}
|
||||||
|
return this.bomMap[bomId];
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchProductMap() {
|
||||||
|
listProduct().then(res => {
|
||||||
|
const map = {};
|
||||||
|
res.data.forEach(item => {
|
||||||
|
map[item.productId] = item;
|
||||||
|
});
|
||||||
|
this.productMap = map;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default useProductStore;
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="reportDetailList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="reportDetailList" @selection-change="handleSelectionChange">
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="reportSummaryList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="reportSummaryList" @selection-change="handleSelectionChange">
|
||||||
|
|||||||
@@ -110,7 +110,7 @@
|
|||||||
>导出
|
>导出
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="expressList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="expressList" @selection-change="handleSelectionChange">
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="expressQuestionList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="expressQuestionList" @selection-change="handleSelectionChange">
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
>导出
|
>导出
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="projectReportList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="projectReportList" @selection-change="handleSelectionChange">
|
||||||
|
|||||||
265
gear-ui3/src/views/product/category/index.vue
Normal file
265
gear-ui3/src/views/product/category/index.vue
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="节点名称" prop="categoryName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.categoryName"
|
||||||
|
placeholder="请输入节点名称"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="节点类型" prop="categoryType">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.categoryType"
|
||||||
|
placeholder="请输入节点类型"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @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="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
icon="Sort"
|
||||||
|
@click="toggleExpandAll"
|
||||||
|
>展开/折叠</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-if="refreshTable"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="productCategoryList"
|
||||||
|
row-key="categoryId"
|
||||||
|
:default-expand-all="isExpandAll"
|
||||||
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||||
|
>
|
||||||
|
<el-table-column label="父节点tree_id" prop="parentId" />
|
||||||
|
<el-table-column label="节点名称" align="center" prop="categoryName" />
|
||||||
|
<el-table-column label="节点类型" align="center" prop="categoryType" />
|
||||||
|
<el-table-column label="同级排序号" align="center" prop="sortNo" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)">新增</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 添加或修改产品分类树对话框 -->
|
||||||
|
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="productCategoryRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="父节点tree_id" prop="parentId">
|
||||||
|
<el-tree-select
|
||||||
|
v-model="form.parentId"
|
||||||
|
:data="productCategoryOptions"
|
||||||
|
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
|
||||||
|
value-key="categoryId"
|
||||||
|
placeholder="请选择父节点tree_id"
|
||||||
|
check-strictly
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="节点名称" prop="categoryName">
|
||||||
|
<el-input v-model="form.categoryName" placeholder="请输入节点名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="节点类型" prop="categoryType">
|
||||||
|
<el-input v-model="form.categoryType" placeholder="请输入节点类型" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="同级排序号" prop="sortNo">
|
||||||
|
<el-input v-model="form.sortNo" placeholder="请输入同级排序号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="ProductCategory">
|
||||||
|
import { listProductCategory, getProductCategory, delProductCategory, addProductCategory, updateProductCategory } from "@/api/oa/productCategory";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const productCategoryList = ref([]);
|
||||||
|
const productCategoryOptions = ref([]);
|
||||||
|
const open = ref(false);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const title = ref("");
|
||||||
|
const isExpandAll = ref(true);
|
||||||
|
const refreshTable = ref(true);
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
form: {},
|
||||||
|
queryParams: {
|
||||||
|
categoryName: undefined,
|
||||||
|
categoryType: undefined,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询产品分类树列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
listProductCategory(queryParams.value).then(response => {
|
||||||
|
productCategoryList.value = proxy.handleTree(response.data, "categoryId", "parentId");
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询产品分类树下拉树结构 */
|
||||||
|
function getTreeselect() {
|
||||||
|
listProductCategory().then(response => {
|
||||||
|
productCategoryOptions.value = [];
|
||||||
|
const data = { categoryId: 0, categoryName: '顶级节点', children: [] };
|
||||||
|
data.children = proxy.handleTree(response.data, "categoryId", "parentId");
|
||||||
|
productCategoryOptions.value.push(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消按钮
|
||||||
|
function cancel() {
|
||||||
|
open.value = false;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单重置
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
categoryId: null,
|
||||||
|
parentId: null,
|
||||||
|
categoryName: null,
|
||||||
|
categoryType: null,
|
||||||
|
sortNo: null,
|
||||||
|
delFlag: null,
|
||||||
|
createTime: null,
|
||||||
|
createBy: null,
|
||||||
|
updateTime: null,
|
||||||
|
updateBy: null,
|
||||||
|
remark: null
|
||||||
|
};
|
||||||
|
proxy.resetForm("productCategoryRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
proxy.resetForm("queryRef");
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function handleAdd(row) {
|
||||||
|
reset();
|
||||||
|
getTreeselect();
|
||||||
|
if (row != null && row.categoryId) {
|
||||||
|
form.value.parentId = row.categoryId;
|
||||||
|
} else {
|
||||||
|
form.value.parentId = 0;
|
||||||
|
}
|
||||||
|
open.value = true;
|
||||||
|
title.value = "添加产品分类树";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
function toggleExpandAll() {
|
||||||
|
refreshTable.value = false;
|
||||||
|
isExpandAll.value = !isExpandAll.value;
|
||||||
|
nextTick(() => {
|
||||||
|
refreshTable.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
async function handleUpdate(row) {
|
||||||
|
loading.value = true;
|
||||||
|
reset();
|
||||||
|
await getTreeselect();
|
||||||
|
if (row != null) {
|
||||||
|
form.value.parentId = row.categoryId;
|
||||||
|
}
|
||||||
|
getProductCategory(row.categoryId).then(response => {
|
||||||
|
loading.value = false;
|
||||||
|
form.value = response.data;
|
||||||
|
open.value = true;
|
||||||
|
title.value = "修改产品分类树";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.$refs["productCategoryRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.categoryId != null) {
|
||||||
|
updateProductCategory(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
}).finally(() => {
|
||||||
|
buttonLoading.value = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addProductCategory(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
}).finally(() => {
|
||||||
|
buttonLoading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
function handleDelete(row) {
|
||||||
|
proxy.$modal.confirm('是否确认删除产品分类树编号为"' + row.categoryId + '"的数据项?').then(function() {
|
||||||
|
loading.value = true;
|
||||||
|
return delProductCategory(row.categoryId);
|
||||||
|
}).then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
getList();
|
||||||
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getList();
|
||||||
|
</script>
|
||||||
254
gear-ui3/src/views/product/components/BomItem.vue
Normal file
254
gear-ui3/src/views/product/components/BomItem.vue
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<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="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="bomItemList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="属性名称" align="center" prop="attrKey" />
|
||||||
|
<el-table-column label="属性值" align="center" prop="attrValue" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@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"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改BOM 明细,存放属性–值对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="属性名称" prop="attrKey">
|
||||||
|
<el-input v-model="form.attrKey" placeholder="请输入属性名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="属性值" prop="attrValue">
|
||||||
|
<el-input v-model="form.attrValue" placeholder="请输入属性值" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listBomItem, getBomItem, delBomItem, addBomItem, updateBomItem } from "@/api/oa/bomItem";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "BomItem",
|
||||||
|
props: {
|
||||||
|
bomId: [String, Number],
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 按钮loading
|
||||||
|
buttonLoading: false,
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// BOM 明细,存放属性–值表格数据
|
||||||
|
bomItemList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
bomId: this.bomId,
|
||||||
|
attrKey: undefined,
|
||||||
|
attrValue: undefined,
|
||||||
|
isEnabled: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {
|
||||||
|
bomId: this.bomId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询BOM 明细,存放属性–值列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
listBomItem(this.queryParams).then(response => {
|
||||||
|
this.bomItemList = response.rows;
|
||||||
|
this.total = response.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
itemId: undefined,
|
||||||
|
bomId: this.bomId,
|
||||||
|
attrKey: undefined,
|
||||||
|
attrValue: undefined,
|
||||||
|
remark: undefined
|
||||||
|
};
|
||||||
|
this.resetForm("form");
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.itemId)
|
||||||
|
this.single = selection.length!==1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset();
|
||||||
|
this.open = true;
|
||||||
|
this.title = "添加BOM 明细,存放属性–值";
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.loading = true;
|
||||||
|
this.reset();
|
||||||
|
const itemId = row.itemId || this.ids
|
||||||
|
getBomItem(itemId).then(response => {
|
||||||
|
this.loading = false;
|
||||||
|
this.form = response.data;
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改BOM 明细,存放属性–值";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.buttonLoading = true;
|
||||||
|
if (this.form.itemId != null) {
|
||||||
|
updateBomItem(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
}).finally(() => {
|
||||||
|
this.buttonLoading = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addBomItem(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
}).finally(() => {
|
||||||
|
this.buttonLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const itemIds = row.itemId || this.ids;
|
||||||
|
this.$modal.confirm('是否确认删除BOM 明细,存放属性–值编号为"' + itemIds + '"的数据项?').then(() => {
|
||||||
|
this.loading = true;
|
||||||
|
return delBomItem(itemIds);
|
||||||
|
}).then(() => {
|
||||||
|
this.loading = false;
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("删除成功");
|
||||||
|
this.$store.dispatch('category/getBomMap');
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('wms/bomItem/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `bomItem_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
230
gear-ui3/src/views/product/components/BomPanel.vue
Normal file
230
gear-ui3/src/views/product/components/BomPanel.vue
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bom-container">
|
||||||
|
<!-- 当没有传入id时显示创建按钮 -->
|
||||||
|
<div v-if="!id" class="create-bom">
|
||||||
|
<el-button type="primary" :loading="createLoading" :disabled="createLoading" @click="handleCreate"
|
||||||
|
class="create-button">
|
||||||
|
<template v-if="!createLoading">
|
||||||
|
<i class="el-icon-plus"></i> 创建BOM
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
创建中...
|
||||||
|
</template>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 当传入id时显示数据区域 -->
|
||||||
|
<div v-else class="bom-details">
|
||||||
|
<div v-if="loading" class="loading-indicator">
|
||||||
|
加载中...
|
||||||
|
<div class="spinner"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="error" class="error-message">
|
||||||
|
加载失败: {{ error }}
|
||||||
|
<button @click="fetchData" class="retry-button">重试</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="data && !loading">
|
||||||
|
<el-form label-width="100px">
|
||||||
|
<el-form-item label="BOM名称">
|
||||||
|
<el-input v-model="info.bomName" @blur="handleUpdateBom" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="BOM编码">
|
||||||
|
<el-input v-model="info.bomCode" @blur="handleUpdateBom" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<BomItem :bomId="id" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { addBom, updateBom, getBom } from '@/api/oa/bom';
|
||||||
|
import { listBomItem } from '@/api/oa/bomItem';
|
||||||
|
import { updateProduct } from '@/api/oa/product';
|
||||||
|
|
||||||
|
import BomItem from './BomItem.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
id: [String, Number], // 支持字符串或数字类型的ID
|
||||||
|
itemId: [String, Number],
|
||||||
|
type: String // 可选类型参数
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BomItem
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
data: null,
|
||||||
|
info: {},
|
||||||
|
createLoading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
id: {
|
||||||
|
immediate: true, // 组件创建时立即执行
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
console.log('侦听到变化')
|
||||||
|
this.fetchBomDetails();
|
||||||
|
} else {
|
||||||
|
// 没有ID时重置数据
|
||||||
|
this.data = null;
|
||||||
|
this.error = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchBomDetails() {
|
||||||
|
try {
|
||||||
|
this.loading = true;
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
|
// 实际项目中替换为真实API调用
|
||||||
|
const response = await listBomItem({
|
||||||
|
bomId: this.id
|
||||||
|
})
|
||||||
|
this.data = response.rows;
|
||||||
|
|
||||||
|
const response2 = await getBom(this.id)
|
||||||
|
this.info = response2.data;
|
||||||
|
} catch (err) {
|
||||||
|
this.error = err.message || '请求失败,请重试';
|
||||||
|
console.error('获取BOM详情失败:', err);
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleCreate() {
|
||||||
|
// 防止重复点击
|
||||||
|
if (this.createLoading) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.createLoading = true;
|
||||||
|
const bomResponse = await addBom({
|
||||||
|
bomName: (this.type == 'product' ? '产品BOM' : '原材料BOM') + new Date().getTime(),
|
||||||
|
bomCode: (this.type == 'product' ? 'P' : 'R') + new Date().getTime()
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$message.success('创建BOM成功');
|
||||||
|
const bomData = bomResponse.data;
|
||||||
|
|
||||||
|
// 根据类型更新产品/原材料
|
||||||
|
await updateProduct({
|
||||||
|
productId: this.itemId,
|
||||||
|
bomId: bomData.bomId
|
||||||
|
});
|
||||||
|
// 触发事件
|
||||||
|
this.$emit('addBom', bomData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建失败:', error);
|
||||||
|
this.$message.error(`创建失败: ${error.message || '未知错误'}`);
|
||||||
|
} finally {
|
||||||
|
this.createLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUpdateBom() {
|
||||||
|
this.$message.warning('正在更新BOM...');
|
||||||
|
updateBom({
|
||||||
|
bomId: this.id,
|
||||||
|
bomName: this.info.bomName,
|
||||||
|
bomCode: this.info.bomCode
|
||||||
|
}).then(_ => {
|
||||||
|
this.$message.success('更新BOM成功');
|
||||||
|
this.$store.dispatch('category/getBomMap');
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchData() {
|
||||||
|
// 重试获取数据
|
||||||
|
if (this.id) this.fetchBomDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.create-bom {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-button {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-button:hover {
|
||||||
|
background-color: #388E3C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-indicator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 3px solid rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: #3498db;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ffebee;
|
||||||
|
color: #d32f2f;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-button {
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bom-info {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #2196F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bom-info p {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
314
gear-ui3/src/views/product/info/index.vue
Normal file
314
gear-ui3/src/views/product/info/index.vue
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="产品编号" prop="productCode">
|
||||||
|
<el-input v-model="queryParams.productCode" placeholder="请输入产品编号" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="产品名称" prop="productName">
|
||||||
|
<el-input v-model="queryParams.productName" placeholder="请输入产品名称" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="负责人" prop="salesManager">
|
||||||
|
<el-input v-model="queryParams.owner" :multiple="false" placeholder="请填写负责人" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="是否启用" prop="isEnabled">
|
||||||
|
<el-select v-model="queryParams.isEnabled" placeholder="请选择是否启用" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in dict.type.common_swicth"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button 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="Plus" size="mini" @click="handleAdd">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="success" plain icon="Edit" size="mini" :disabled="single"
|
||||||
|
@click="handleUpdate">修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" size="mini" :disabled="multiple"
|
||||||
|
@click="handleDelete">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" size="mini" @click="handleExport">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="productList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="产品编号" align="center" prop="productCode" />
|
||||||
|
<el-table-column label="产品名称" align="center" prop="productName" />
|
||||||
|
<el-table-column label="负责人" align="center" prop="owner" />
|
||||||
|
<el-table-column label="BOM" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<BomInfoMini :bomId="scope.row.bomId" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
<!-- <el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-document"
|
||||||
|
@click="goLedger(scope.row)"
|
||||||
|
>台账</el-button> -->
|
||||||
|
<el-button size="mini" type="text" icon="Document"
|
||||||
|
@click="handleInstallManual(scope.row)">安装说明书</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="DataAnalysis" @click="handleBom(scope.row)">BOM</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-dialog :title="title" v-model="open" width="800px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="产品编号" prop="productCode">
|
||||||
|
<el-input v-model="form.productCode" placeholder="请输入产品编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="产品名称" prop="productName">
|
||||||
|
<el-input v-model="form.productName" placeholder="请输入产品名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="负责人" prop="owner">
|
||||||
|
<el-input v-model="form.owner" :multiple="false" placeholder="请填写负责人" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog title="BOM" @close="bomDialogVisible = false" v-model="bomDialogVisible" width="900px" append-to-body>
|
||||||
|
<BomPanel :id="bomId" type="product" @addBom="handleAddBom" :itemId="itemId" />
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listProduct, getProduct, delProduct, addProduct, updateProduct } from "@/api/oa/product";
|
||||||
|
import UserSelect from '@/components/UserSelect';
|
||||||
|
import BomPanel from '../components/BomPanel.vue';
|
||||||
|
import BomInfoMini from '@/components/Renderer/BomInfoMini.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Product",
|
||||||
|
components: {
|
||||||
|
UserSelect,
|
||||||
|
BomPanel,
|
||||||
|
BomInfoMini
|
||||||
|
},
|
||||||
|
// dicts: ['common_swicth'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 按钮loading
|
||||||
|
buttonLoading: false,
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 产品表格数据
|
||||||
|
productList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
type: 'product',
|
||||||
|
productCode: undefined,
|
||||||
|
productName: undefined,
|
||||||
|
owner: undefined,
|
||||||
|
baseMaterialId: undefined,
|
||||||
|
surfaceTreatmentId: undefined,
|
||||||
|
customerReqId: undefined,
|
||||||
|
packagingId: undefined,
|
||||||
|
thickness: undefined,
|
||||||
|
width: undefined,
|
||||||
|
innerDiameter: undefined,
|
||||||
|
isEnabled: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
productCode: [
|
||||||
|
{ required: true, message: "产品编号不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
productName: [
|
||||||
|
{ required: true, message: "产品名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
owner: [
|
||||||
|
{ required: true, message: "负责人不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
bomDialogVisible: false,
|
||||||
|
bomId: undefined,
|
||||||
|
itemId: undefined,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询产品列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
listProduct(this.queryParams).then(response => {
|
||||||
|
this.productList = response.rows;
|
||||||
|
this.total = response.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleAddBom(bom) {
|
||||||
|
this.bomId = bom.bomId;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
productId: undefined,
|
||||||
|
productCode: undefined,
|
||||||
|
productName: undefined,
|
||||||
|
owner: undefined,
|
||||||
|
baseMaterialId: undefined,
|
||||||
|
surfaceTreatmentId: undefined,
|
||||||
|
customerReqId: undefined,
|
||||||
|
packagingId: undefined,
|
||||||
|
thickness: undefined,
|
||||||
|
width: undefined,
|
||||||
|
innerDiameter: undefined,
|
||||||
|
isEnabled: undefined,
|
||||||
|
unit: undefined,
|
||||||
|
delFlag: undefined,
|
||||||
|
createTime: undefined,
|
||||||
|
createBy: undefined,
|
||||||
|
updateTime: undefined,
|
||||||
|
updateBy: undefined,
|
||||||
|
type: 'product'
|
||||||
|
};
|
||||||
|
this.resetForm("form");
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
handleInstallManual(row) {
|
||||||
|
console.log(row);
|
||||||
|
},
|
||||||
|
handleBom(row) {
|
||||||
|
this.bomDialogVisible = true;
|
||||||
|
this.bomId = row.bomId;
|
||||||
|
this.itemId = row.productId;
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.productId)
|
||||||
|
this.single = selection.length !== 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset();
|
||||||
|
this.open = true;
|
||||||
|
this.title = "添加产品";
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.loading = true;
|
||||||
|
this.reset();
|
||||||
|
const productId = row.productId || this.ids
|
||||||
|
getProduct(productId).then(response => {
|
||||||
|
this.loading = false;
|
||||||
|
this.form = response.data;
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改产品";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.buttonLoading = true;
|
||||||
|
if (this.form.productId != null) {
|
||||||
|
updateProduct(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
// this.$store.dispatch('category/getProductMap');
|
||||||
|
}).finally(() => {
|
||||||
|
this.buttonLoading = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addProduct(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
// this.$store.dispatch('category/getProductMap');
|
||||||
|
}).finally(() => {
|
||||||
|
this.buttonLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const productIds = row.productId || this.ids;
|
||||||
|
this.$modal.confirm('是否确认删除产品编号为"' + productIds + '"的数据项?').then(() => {
|
||||||
|
this.loading = true;
|
||||||
|
return delProduct(productIds);
|
||||||
|
}).then(() => {
|
||||||
|
this.loading = false;
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("删除成功");
|
||||||
|
// this.$store.dispatch('category/getProductMap');
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('wms/product/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `product_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
BIN
node_modules/.pnpm/@esbuild+win32-x64@0.25.8/node_modules/@esbuild/win32-x64/esbuild.exe
generated
vendored
BIN
node_modules/.pnpm/@esbuild+win32-x64@0.25.8/node_modules/@esbuild/win32-x64/esbuild.exe
generated
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user