Merge remote-tracking branch 'origin/main'

main
liutao 2 weeks ago
commit 45f9df08f0

@ -8,18 +8,19 @@ export interface ProductCategoryVO {
code: string // 分类编码 code: string // 分类编码
sort: number // 分类排序 sort: number // 分类排序
status: number // 开启状态 status: number // 开启状态
type: number // 类型
} }
// ERP 产品分类 API // ERP 产品分类 API
export const ProductCategoryApi = { export const ProductCategoryApi = {
// 查询产品分类列表 // 查询产品分类列表
getProductCategoryList: async () => { getProductCategoryList: async (type?: number) => {
return await request.get({ url: `/erp/product-category/list` }) return await request.get({ url: `/erp/product-category/list`, params: { type } })
}, },
// 查询产品分类精简列表 // 查询产品分类精简列表
getProductCategorySimpleList: async () => { getProductCategorySimpleList: async (type?: number) => {
return await request.get({ url: `/erp/product-category/simple-list` }) return await request.get({ url: `/erp/product-category/simple-list`, params: { type } })
}, },
// 查询产品分类详情 // 查询产品分类详情

@ -49,8 +49,8 @@ export const ProductApi = {
return await request.get({ url: `/erp/product/simple-list-order` }) return await request.get({ url: `/erp/product/simple-list-order` })
}, },
// 查询所有商品精简列表 // 查询所有商品精简列表
getMesProductSimpleList: async () => { getMesProductSimpleList: async (params?: { categoryType?: number }) => {
return await request.get({ url: `/erp/product/simple-list-product` }) return await request.get({ url: `/erp/product/simple-list-product`, params })
}, },
// 查询备件精简列表 // 查询备件精简列表
getComponentSimpleList: async () => { getComponentSimpleList: async () => {

@ -1990,17 +1990,19 @@ export default {
dialogCodePlaceholder: 'Please enter code', dialogCodePlaceholder: 'Please enter code',
dialogNameLabel: 'Name', dialogNameLabel: 'Name',
dialogNamePlaceholder: 'Please enter name', dialogNamePlaceholder: 'Please enter name',
dialogTypeLabel: 'Type',
dialogSortLabel: 'Sort', dialogSortLabel: 'Sort',
dialogSortPlaceholder: 'Please enter sort', dialogSortPlaceholder: 'Please enter sort',
dialogStatusLabel: 'Status', dialogStatusLabel: 'Status',
dialogCancelButton: 'Cancel', dialogCancelButton: 'Cancel',
dialogSubmitButton: 'Confirm', dialogSubmitButton: 'Confirm',
treeRootName: 'Top Product Category', treeRootName: 'Top Category',
validatorParentRequired: 'Parent category can not be empty', validatorParentRequired: 'Parent category can not be empty',
validatorNameRequired: 'Name can not be empty', validatorNameRequired: 'Name can not be empty',
validatorCodeRequired: 'Code can not be empty', validatorCodeRequired: 'Code can not be empty',
validatorSortRequired: 'Sort can not be empty', validatorSortRequired: 'Sort can not be empty',
validatorStatusRequired: 'Status can not be empty' validatorStatusRequired: 'Status can not be empty',
validatorTypeRequired: 'Type can not be empty'
}, },
ProductInformation: { ProductInformation: {
moduleName: 'Product Material Information', moduleName: 'Product Material Information',
@ -2053,6 +2055,7 @@ export default {
validatorNameRequired: 'Product name can not be empty', validatorNameRequired: 'Product name can not be empty',
validatorBarCodeRequired: 'Product barcode can not be empty', validatorBarCodeRequired: 'Product barcode can not be empty',
validatorCategoryRequired: 'Product category id can not be empty', validatorCategoryRequired: 'Product category id can not be empty',
validatorCategoryTypeRequired: 'Type can not be empty',
validatorUnitRequired: 'Unit id can not be empty', validatorUnitRequired: 'Unit id can not be empty',
validatorStatusRequired: 'Product status can not be empty' validatorStatusRequired: 'Product status can not be empty'
}, },

@ -2855,17 +2855,19 @@ export default {
dialogCodePlaceholder: '请输入编码', dialogCodePlaceholder: '请输入编码',
dialogNameLabel: '名称', dialogNameLabel: '名称',
dialogNamePlaceholder: '请输入名称', dialogNamePlaceholder: '请输入名称',
dialogTypeLabel: '类型',
dialogSortLabel: '排序', dialogSortLabel: '排序',
dialogSortPlaceholder: '请输入排序', dialogSortPlaceholder: '请输入排序',
dialogStatusLabel: '状态', dialogStatusLabel: '状态',
dialogCancelButton: '取 消', dialogCancelButton: '取 消',
dialogSubmitButton: '确 定', dialogSubmitButton: '确 定',
treeRootName: '顶级产品分类', treeRootName: '顶级分类',
validatorParentRequired: '上级编号不能为空', validatorParentRequired: '上级编号不能为空',
validatorNameRequired: '名称不能为空', validatorNameRequired: '名称不能为空',
validatorCodeRequired: '编码不能为空', validatorCodeRequired: '编码不能为空',
validatorSortRequired: '排序不能为空', validatorSortRequired: '排序不能为空',
validatorStatusRequired: '状态不能为空' validatorStatusRequired: '状态不能为空',
validatorTypeRequired: '类型不能为空'
}, },
ProductInformation: { ProductInformation: {
moduleName: '产品物料信息', moduleName: '产品物料信息',
@ -2892,6 +2894,7 @@ export default {
dialogBarCodePlaceholder: '请输入编码', dialogBarCodePlaceholder: '请输入编码',
dialogNameLabel: '名称', dialogNameLabel: '名称',
dialogNamePlaceholder: '请输入名称', dialogNamePlaceholder: '请输入名称',
dialogCategoryTypeLabel: '类型',
dialogCategoryLabel: '分类', dialogCategoryLabel: '分类',
dialogCategoryPlaceholder: '请选择分类', dialogCategoryPlaceholder: '请选择分类',
dialogUnitLabel: '单位', dialogUnitLabel: '单位',
@ -2918,6 +2921,7 @@ export default {
validatorNameRequired: '产品名称不能为空', validatorNameRequired: '产品名称不能为空',
validatorBarCodeRequired: '产品条码不能为空', validatorBarCodeRequired: '产品条码不能为空',
validatorCategoryRequired: '产品分类编号不能为空', validatorCategoryRequired: '产品分类编号不能为空',
validatorCategoryTypeRequired: '类型不能为空',
validatorUnitRequired: '单位编号不能为空', validatorUnitRequired: '单位编号不能为空',
validatorStatusRequired: '产品状态不能为空' validatorStatusRequired: '产品状态不能为空'
}, },

@ -234,6 +234,7 @@ export enum DICT_TYPE {
ERP_AUTOCODE_PADDING_TYPE = "erp_autocode_padding_type", ERP_AUTOCODE_PADDING_TYPE = "erp_autocode_padding_type",
ERP_AUTOCODE_CYCLEMETHOD = "erp_autocode_cyclemethod", ERP_AUTOCODE_CYCLEMETHOD = "erp_autocode_cyclemethod",
ERP_AUTOCODE_PARTTYPE = "erp_autocode_parttype", ERP_AUTOCODE_PARTTYPE = "erp_autocode_parttype",
MATERIAL_CLASSIFICATION_TYPE = 'material_classification_type',
// ========== MES - 生产管理模块 ========== // ========== MES - 生产管理模块 ==========

@ -7,6 +7,17 @@
label-width="120px" label-width="120px"
v-loading="formLoading" v-loading="formLoading"
> >
<el-form-item :label="t('FactoryModeling.ProductCategory.dialogTypeLabel')" prop="type">
<el-radio-group v-model="formData.type" @change="handleTypeChange">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('FactoryModeling.ProductCategory.dialogParentLabel')" prop="parentId"> <el-form-item :label="t('FactoryModeling.ProductCategory.dialogParentLabel')" prop="parentId">
<el-tree-select <el-tree-select
v-model="formData.parentId" v-model="formData.parentId"
@ -66,14 +77,16 @@ const formData = ref({
name: undefined, name: undefined,
code: undefined, code: undefined,
sort: undefined, sort: undefined,
status: CommonStatusEnum.ENABLE status: CommonStatusEnum.ENABLE,
type: undefined
}) })
const formRules = reactive({ const formRules = reactive({
parentId: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorParentRequired'), trigger: 'blur' }], parentId: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorParentRequired'), trigger: 'blur' }],
name: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorNameRequired'), trigger: 'blur' }], name: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorNameRequired'), trigger: 'blur' }],
code: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorCodeRequired'), trigger: 'blur' }], code: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorCodeRequired'), trigger: 'blur' }],
sort: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorSortRequired'), trigger: 'blur' }], sort: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorSortRequired'), trigger: 'blur' }],
status: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorStatusRequired'), trigger: 'blur' }] status: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorStatusRequired'), trigger: 'blur' }],
type: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorTypeRequired'), trigger: 'change' }]
}) })
const formRef = ref() // Ref const formRef = ref() // Ref
const productCategoryTree = ref() // const productCategoryTree = ref() //
@ -84,6 +97,12 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
formType.value = type formType.value = type
resetForm() resetForm()
if (!id) {
const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)
if (typeOptions.length > 0) {
formData.value.type = typeOptions[0].value
}
}
// //
if (id) { if (id) {
formLoading.value = true formLoading.value = true
@ -129,7 +148,8 @@ const resetForm = () => {
name: undefined, name: undefined,
code: undefined, code: undefined,
sort: undefined, sort: undefined,
status: CommonStatusEnum.ENABLE status: CommonStatusEnum.ENABLE,
type: undefined
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }
@ -137,9 +157,15 @@ const resetForm = () => {
/** 获得产品分类树 */ /** 获得产品分类树 */
const getProductCategoryTree = async () => { const getProductCategoryTree = async () => {
productCategoryTree.value = [] productCategoryTree.value = []
const data = await ProductCategoryApi.getProductCategoryList() const data = await ProductCategoryApi.getProductCategoryList(formData.value.type)
const root: Tree = { id: 0, name: t('FactoryModeling.ProductCategory.treeRootName'), children: [] } const root: Tree = { id: 0, name: t('FactoryModeling.ProductCategory.treeRootName'), children: [] }
root.children = handleTree(data, 'id', 'parentId') root.children = handleTree(data, 'id', 'parentId')
productCategoryTree.value.push(root) productCategoryTree.value.push(root)
} }
/** 类型变更时刷新上级编号树 */
const handleTypeChange = async () => {
formData.value.parentId = undefined
await getProductCategoryTree()
}
</script> </script>

@ -61,6 +61,14 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <ContentWrap>
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
<el-tab-pane
v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)"
:key="dict.value"
:label="dict.label"
:name="String(dict.value)"
/>
</el-tabs>
<el-table <el-table
v-loading="loading" v-loading="loading"
:data="list" :data="list"
@ -136,9 +144,11 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // const loading = ref(true) //
const list = ref<ProductCategoryVO[]>([]) // const list = ref<ProductCategoryVO[]>([]) //
const activeTab = ref('') // tab
const queryParams = reactive({ const queryParams = reactive({
name: undefined, name: undefined,
status: undefined status: undefined,
type: undefined
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
const exportLoading = ref(false) // const exportLoading = ref(false) //
@ -147,7 +157,7 @@ const exportLoading = ref(false) // 导出的加载中
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
try { try {
const data = await ProductCategoryApi.getProductCategoryList(queryParams) const data = await ProductCategoryApi.getProductCategoryList(queryParams.type)
list.value = handleTree(data, 'id', 'parentId') list.value = handleTree(data, 'id', 'parentId')
} finally { } finally {
loading.value = false loading.value = false
@ -160,6 +170,12 @@ const handleQuery = () => {
getList() getList()
} }
/** Tab 切换操作 */
const handleTabChange = (name: string) => {
queryParams.type = name ? Number(name) : undefined
getList()
}
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value.resetFields()
@ -212,6 +228,11 @@ const toggleExpandAll = async () => {
/** 初始化 **/ /** 初始化 **/
onMounted(() => { onMounted(() => {
const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)
if (typeOptions.length > 0) {
activeTab.value = String(typeOptions[0].value)
queryParams.type = typeOptions[0].value
}
getList() getList()
}) })
</script> </script>

@ -31,6 +31,19 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item :label="t('FactoryModeling.ProductInformation.dialogCategoryTypeLabel')" prop="categoryType">
<el-radio-group v-model="formData.categoryType" @change="handleCategoryTypeChange">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('FactoryModeling.ProductInformation.dialogNameLabel')" prop="name"> <el-form-item :label="t('FactoryModeling.ProductInformation.dialogNameLabel')" prop="name">
<el-input v-model="formData.name" :placeholder="t('FactoryModeling.ProductInformation.dialogNamePlaceholder')" /> <el-input v-model="formData.name" :placeholder="t('FactoryModeling.ProductInformation.dialogNamePlaceholder')" />
@ -253,6 +266,7 @@ const formData = ref({
isCode: undefined, isCode: undefined,
qrcodeUrl: undefined, qrcodeUrl: undefined,
templateJson: undefined, templateJson: undefined,
categoryType: undefined,
categoryId: undefined, categoryId: undefined,
unitId: undefined, unitId: undefined,
status: undefined, status: undefined,
@ -432,6 +446,7 @@ const validateBarCode = (_rule, value, callback) => {
callback() callback()
} }
const formRules = reactive({ const formRules = reactive({
categoryType: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryTypeRequired'), trigger: 'change' }],
name: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorNameRequired'), trigger: 'blur' }], name: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorNameRequired'), trigger: 'blur' }],
barCode: [{ validator: validateBarCode, trigger: ['blur', 'change'] }], barCode: [{ validator: validateBarCode, trigger: ['blur', 'change'] }],
categoryId: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryRequired'), trigger: 'blur' }], categoryId: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryRequired'), trigger: 'blur' }],
@ -449,9 +464,12 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
formType.value = type formType.value = type
resetForm() resetForm()
const categoryData = await ProductCategoryApi.getProductCategorySimpleList() if (!id) {
categoryList.value = handleTree(categoryData, 'id', 'parentId') const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)
unitList.value = await ProductUnitApi.getProductUnitSimpleList() if (typeOptions.length > 0) {
formData.value.categoryType = typeOptions[0].value
}
}
if (id) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
@ -485,6 +503,9 @@ const open = async (type: string, id?: number) => {
formLoading.value = false formLoading.value = false
} }
} }
const categoryData = await ProductCategoryApi.getProductCategorySimpleList(formData.value.categoryType)
categoryList.value = handleTree(categoryData, 'id', 'parentId')
unitList.value = await ProductUnitApi.getProductUnitSimpleList()
} }
defineExpose({ open }) defineExpose({ open })
@ -507,6 +528,12 @@ const handleCodeAutoChange = (value: boolean) => {
formRef.value?.clearValidate('barCode') formRef.value?.clearValidate('barCode')
} }
const handleCategoryTypeChange = async () => {
formData.value.categoryId = undefined
const categoryData = await ProductCategoryApi.getProductCategorySimpleList(formData.value.categoryType)
categoryList.value = handleTree(categoryData, 'id', 'parentId')
}
const getQrcodeRefreshUrl = () => { const getQrcodeRefreshUrl = () => {
if (!formData.value.id || !formData.value.barCode) return '' if (!formData.value.id || !formData.value.barCode) return ''
return `/erp/product/regenerate-code?id=${formData.value.id}&code=${encodeURIComponent(String(formData.value.barCode))}` return `/erp/product/regenerate-code?id=${formData.value.id}&code=${encodeURIComponent(String(formData.value.barCode))}`
@ -572,6 +599,7 @@ const resetForm = () => {
barCode: undefined, barCode: undefined,
isCode: true, isCode: true,
qrcodeUrl: undefined, qrcodeUrl: undefined,
categoryType: undefined,
categoryId: undefined, categoryId: undefined,
unitId: undefined, unitId: undefined,
status: CommonStatusEnum.ENABLE, status: CommonStatusEnum.ENABLE,

@ -33,8 +33,13 @@
</ContentWrap> </ContentWrap>
<ContentWrap> <ContentWrap>
<el-tabs v-model="activeName" @tab-click="handleTabClick"> <el-tabs v-model="activeName" @tab-change="handleTabChange">
<el-tab-pane v-for="item in parentList" :key="item.id" :label="item.name" :name="item.id.toString()" /> <el-tab-pane
v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)"
:key="dict.value"
:label="dict.label"
:name="String(dict.value)"
/>
</el-tabs> </el-tabs>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column :label="t('FactoryModeling.ProductInformation.tableBarCodeColumn')" align="center" prop="barCode" <el-table-column :label="t('FactoryModeling.ProductInformation.tableBarCodeColumn')" align="center" prop="barCode"
@ -80,10 +85,8 @@
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import ProductForm from './ProductForm.vue' import ProductForm from './ProductForm.vue'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { handleTree } from '@/utils/tree'
import BomForm from "@/views/mes/bom/BomForm.vue"; import BomForm from "@/views/mes/bom/BomForm.vue";
/** ERP 产品列表 */ /** ERP 产品列表 */
@ -100,12 +103,11 @@ const queryParams = reactive({
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
barCode: undefined, barCode: undefined,
categoryId: undefined categoryId: undefined,
categoryType: undefined
}) })
const queryFormRef = ref() const queryFormRef = ref()
const exportLoading = ref(false) const exportLoading = ref(false)
const categoryList = ref<ProductCategoryVO[]>([])
const parentList = ref<ProductCategoryVO[]>([])
const formVisible = ref(false) const formVisible = ref(false)
const formType = ref('') const formType = ref('')
@ -161,21 +163,17 @@ const handleExport = async () => {
} }
onMounted(async () => { onMounted(async () => {
queryParams.categoryId = 2 const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)
await getList() if (typeOptions.length > 0) {
const categoryData = await ProductCategoryApi.getProductCategorySimpleList() activeName = String(typeOptions[0].value)
categoryList.value = handleTree(categoryData, 'id', 'parentId') queryParams.categoryType = typeOptions[0].value
for (let i = 0; i < categoryData.length; i++) {
if (categoryData[i].parentId === 0) {
parentList.value.push(categoryData[i]);
}
} }
parentList.value.sort((a, b) => a.sort - b.sort); await getList()
}) })
let activeName = '2' let activeName = ''
const handleTabClick = (tab: TabsPaneContext) => { const handleTabChange = (name: string) => {
queryParams.categoryId = tab.paneName queryParams.categoryType = name ? Number(name) : undefined
handleQuery() handleQuery()
} }

@ -117,7 +117,7 @@ const open = async (type: string, id?: number) => {
} }
} }
unitList.value = await ProductUnitApi.getProductUnitSimpleList() unitList.value = await ProductUnitApi.getProductUnitSimpleList()
productList.value = await ProductApi.getMesProductSimpleList() productList.value = await ProductApi.getMesProductSimpleList({ categoryType: 1 })
} }
defineExpose({ open }) defineExpose({ open })

@ -256,6 +256,6 @@ const handleExport = async () => {
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
await getList() await getList()
productList.value = await ProductApi.getMesProductSimpleList() productList.value = await ProductApi.getMesProductSimpleList({ categoryType: 1 })
}) })
</script> </script>

Loading…
Cancel
Save