feat(wms):增加商品信息、SKU 信息
parent
30e4fef7bb
commit
d890781149
|
|
@ -0,0 +1,55 @@
|
||||||
|
import request from '@/config/axios'
|
||||||
|
import { ItemSkuVO } from './sku'
|
||||||
|
|
||||||
|
// WMS 商品 VO
|
||||||
|
export interface ItemVO {
|
||||||
|
id?: number
|
||||||
|
code?: string
|
||||||
|
name?: string
|
||||||
|
categoryId?: number
|
||||||
|
categoryName?: string
|
||||||
|
unit?: string
|
||||||
|
brandId?: number
|
||||||
|
brandName?: string
|
||||||
|
remark?: string
|
||||||
|
skus?: ItemSkuVO[]
|
||||||
|
createTime?: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
// WMS 商品 API
|
||||||
|
export const ItemApi = {
|
||||||
|
// 查询商品分页
|
||||||
|
getItemPage: async (params: any) => {
|
||||||
|
return await request.get({ url: '/wms/item/page', params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询商品精简列表
|
||||||
|
getItemSimpleList: async (params?: any) => {
|
||||||
|
return await request.get({ url: '/wms/item/simple-list', params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询商品详情
|
||||||
|
getItem: async (id: number) => {
|
||||||
|
return await request.get({ url: '/wms/item/get?id=' + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增商品
|
||||||
|
createItem: async (data: ItemVO) => {
|
||||||
|
return await request.post({ url: '/wms/item/create', data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改商品
|
||||||
|
updateItem: async (data: ItemVO) => {
|
||||||
|
return await request.put({ url: '/wms/item/update', data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除商品
|
||||||
|
deleteItem: async (id: number) => {
|
||||||
|
return await request.delete({ url: '/wms/item/delete?id=' + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出商品
|
||||||
|
exportItem: async (params: any) => {
|
||||||
|
return await request.download({ url: '/wms/item/export-excel', params })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// WMS 商品 SKU VO
|
||||||
|
export interface ItemSkuVO {
|
||||||
|
id?: number
|
||||||
|
name?: string
|
||||||
|
itemId?: number
|
||||||
|
itemCode?: string
|
||||||
|
itemName?: string
|
||||||
|
categoryId?: number
|
||||||
|
categoryName?: string
|
||||||
|
unit?: string
|
||||||
|
brandId?: number
|
||||||
|
brandName?: string
|
||||||
|
barCode?: string
|
||||||
|
code?: string
|
||||||
|
length?: number
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
grossWeight?: number
|
||||||
|
netWeight?: number
|
||||||
|
costPrice?: number
|
||||||
|
sellingPrice?: number
|
||||||
|
createTime?: Date
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,291 @@
|
||||||
|
<!-- WMS 商品表单 -->
|
||||||
|
<template>
|
||||||
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="1200px">
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
v-loading="formLoading"
|
||||||
|
:model="formData"
|
||||||
|
:rules="formRules"
|
||||||
|
label-width="88px"
|
||||||
|
>
|
||||||
|
<!-- 基础信息 -->
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品名称" prop="name">
|
||||||
|
<el-input v-model="formData.name" maxlength="60" placeholder="请输入商品名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品分类" prop="categoryId">
|
||||||
|
<ItemCategorySelect v-model="formData.categoryId" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品编号" prop="code">
|
||||||
|
<el-input v-model="formData.code" maxlength="20" placeholder="请输入商品编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品单位" prop="unit">
|
||||||
|
<el-input v-model="formData.unit" maxlength="20" placeholder="请输入单位" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品品牌" prop="brandId">
|
||||||
|
<ItemBrandSelect v-model="formData.brandId" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="formData.remark" maxlength="255" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 规格信息 -->
|
||||||
|
<div class="mb-12px flex items-center justify-between">
|
||||||
|
<span class="text-14px font-bold">规格</span>
|
||||||
|
<el-button plain type="primary" @click="handleAddSku">
|
||||||
|
<Icon class="mr-5px" icon="ep:plus" />
|
||||||
|
新增规格
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="formData.skus" border>
|
||||||
|
<el-table-column label="规格名称" min-width="150">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-form-item
|
||||||
|
:prop="'skus.' + scope.$index + '.name'"
|
||||||
|
:rules="skuNameRules"
|
||||||
|
class="!mb-0 !w-1/1"
|
||||||
|
label-width="0"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="scope.row.name"
|
||||||
|
maxlength="255"
|
||||||
|
class="!w-1/1"
|
||||||
|
placeholder="请输入规格名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="编号/条码" width="220">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input v-model="scope.row.code" maxlength="64" class="!w-1/1" placeholder="编号" />
|
||||||
|
<el-input
|
||||||
|
v-model="scope.row.barCode"
|
||||||
|
maxlength="64"
|
||||||
|
class="!w-1/1 mt-5px"
|
||||||
|
placeholder="条码为空时,提交后自动生成"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="长/宽/高(cm)" width="210">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="flex w-1/1 gap-5px">
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.length"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="DIMENSION_PRECISION"
|
||||||
|
class="!w-1/3"
|
||||||
|
placeholder="长"
|
||||||
|
/>
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.width"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="DIMENSION_PRECISION"
|
||||||
|
class="!w-1/3"
|
||||||
|
placeholder="宽"
|
||||||
|
/>
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.height"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="DIMENSION_PRECISION"
|
||||||
|
class="!w-1/3"
|
||||||
|
placeholder="高"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="净重/毛重(kg)" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.netWeight"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="WEIGHT_PRECISION"
|
||||||
|
class="!w-1/1"
|
||||||
|
placeholder="净重"
|
||||||
|
/>
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.grossWeight"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="WEIGHT_PRECISION"
|
||||||
|
class="!w-1/1 mt-5px"
|
||||||
|
placeholder="毛重"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="成本价/销售价" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.costPrice"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="PRICE_PRECISION"
|
||||||
|
class="!w-1/1"
|
||||||
|
placeholder="成本价"
|
||||||
|
/>
|
||||||
|
<el-input-number
|
||||||
|
v-model="scope.row.sellingPrice"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:precision="PRICE_PRECISION"
|
||||||
|
class="!w-1/1 mt-5px"
|
||||||
|
placeholder="销售价"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="操作" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="danger" @click="handleDeleteSku(scope.$index)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { FormRules } from 'element-plus'
|
||||||
|
import { ItemApi, ItemVO } from '@/api/wms/md/item'
|
||||||
|
import { ItemSkuVO } from '@/api/wms/md/item/sku'
|
||||||
|
import { DIMENSION_PRECISION, PRICE_PRECISION, WEIGHT_PRECISION } from '@/views/wms/utils/format'
|
||||||
|
import ItemBrandSelect from './brand/components/ItemBrandSelect.vue'
|
||||||
|
import ItemCategorySelect from './category/components/ItemCategorySelect.vue'
|
||||||
|
|
||||||
|
/** WMS 商品表单 */
|
||||||
|
defineOptions({ name: 'WmsItemForm' })
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
|
const formLoading = ref(false) // 表单的加载中
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
const formData = ref<ItemVO>({
|
||||||
|
id: undefined,
|
||||||
|
code: undefined,
|
||||||
|
name: undefined,
|
||||||
|
categoryId: undefined,
|
||||||
|
unit: undefined,
|
||||||
|
brandId: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
skus: []
|
||||||
|
})
|
||||||
|
const formRules = reactive<FormRules>({
|
||||||
|
name: [{ required: true, message: '商品名称不能为空', trigger: 'blur' }],
|
||||||
|
categoryId: [{ required: true, message: '商品分类不能为空', trigger: 'change' }],
|
||||||
|
skus: [{ required: true, message: '至少包含一个商品规格', trigger: 'change' }]
|
||||||
|
})
|
||||||
|
const skuNameRules = [{ required: true, message: '规格名称不能为空', trigger: 'blur' }]
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
|
// 修改时,设置数据
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const item = await ItemApi.getItem(id)
|
||||||
|
formData.value = {
|
||||||
|
...item,
|
||||||
|
skus: item.skus?.length ? item.skus : [buildEmptySku()]
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
/** 构建空规格 */
|
||||||
|
const buildEmptySku = (): ItemSkuVO => ({
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
barCode: undefined,
|
||||||
|
code: undefined,
|
||||||
|
length: undefined,
|
||||||
|
width: undefined,
|
||||||
|
height: undefined,
|
||||||
|
grossWeight: undefined,
|
||||||
|
netWeight: undefined,
|
||||||
|
costPrice: undefined,
|
||||||
|
sellingPrice: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 添加规格 */
|
||||||
|
const handleAddSku = () => {
|
||||||
|
formData.value.skus?.push(buildEmptySku())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除规格 */
|
||||||
|
const handleDeleteSku = (index: number) => {
|
||||||
|
if (!formData.value.skus || formData.value.skus.length <= 1) {
|
||||||
|
message.error('至少包含一个商品规格')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.value.skus.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 校验表单
|
||||||
|
await formRef.value.validate()
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = formData.value as ItemVO
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await ItemApi.createItem(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await ItemApi.updateItem(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
formData.value = {
|
||||||
|
id: undefined,
|
||||||
|
code: undefined,
|
||||||
|
name: undefined,
|
||||||
|
categoryId: undefined,
|
||||||
|
unit: undefined,
|
||||||
|
brandId: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
skus: [buildEmptySku()]
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<!-- WMS 商品品牌选择器 -->
|
||||||
|
<template>
|
||||||
|
<el-select
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-model="selectValue"
|
||||||
|
:clearable="clearable"
|
||||||
|
:disabled="disabled"
|
||||||
|
:filter-method="handleFilter"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
class="w-1/1"
|
||||||
|
filterable
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="brand in filteredList"
|
||||||
|
:key="brand.id!"
|
||||||
|
:label="brand.name"
|
||||||
|
:value="brand.id!"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ItemBrandApi, ItemBrandVO } from '@/api/wms/md/item/brand'
|
||||||
|
|
||||||
|
/** WMS 商品品牌选择器 */
|
||||||
|
defineOptions({ name: 'WmsItemBrandSelect', inheritAttrs: false })
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
modelValue?: number
|
||||||
|
disabled?: boolean
|
||||||
|
clearable?: boolean
|
||||||
|
placeholder?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请选择商品品牌'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: number | undefined]
|
||||||
|
change: [brand: ItemBrandVO | undefined]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const brandList = ref<ItemBrandVO[]>([]) // 品牌列表
|
||||||
|
const filteredList = ref<ItemBrandVO[]>([]) // 过滤后的品牌列表
|
||||||
|
|
||||||
|
const selectValue = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 前端过滤 */
|
||||||
|
const handleFilter = (query: string) => {
|
||||||
|
if (!query) {
|
||||||
|
filteredList.value = brandList.value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const keyword = query.toLowerCase()
|
||||||
|
filteredList.value = brandList.value.filter((brand) =>
|
||||||
|
brand.name?.toLowerCase().includes(keyword)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选中变化 */
|
||||||
|
const handleChange = (value: number | undefined) => {
|
||||||
|
emit(
|
||||||
|
'change',
|
||||||
|
brandList.value.find((brand) => brand.id === value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
brandList.value = await ItemBrandApi.getItemBrandSimpleList()
|
||||||
|
filteredList.value = brandList.value
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -23,7 +23,12 @@
|
||||||
<el-input v-model="formData.name" placeholder="请输入分类名称" />
|
<el-input v-model="formData.name" placeholder="请输入分类名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="显示排序" prop="sort">
|
<el-form-item label="显示排序" prop="sort">
|
||||||
<el-input-number v-model="formData.sort" :min="0" class="!w-1/1" controls-position="right" />
|
<el-input-number
|
||||||
|
v-model="formData.sort"
|
||||||
|
:min="0"
|
||||||
|
class="!w-1/1"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
<el-select v-model="formData.status" clearable placeholder="请选择状态">
|
<el-select v-model="formData.status" clearable placeholder="请选择状态">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<!-- WMS 商品分类选择器 -->
|
||||||
|
<template>
|
||||||
|
<el-tree-select
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-model="selectValue"
|
||||||
|
:data="categoryTree"
|
||||||
|
:disabled="disabled"
|
||||||
|
:props="defaultProps"
|
||||||
|
check-strictly
|
||||||
|
class="w-1/1"
|
||||||
|
default-expand-all
|
||||||
|
:placeholder="placeholder"
|
||||||
|
value-key="id"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { defaultProps, handleTree } from '@/utils/tree'
|
||||||
|
import { ItemCategoryApi, ItemCategoryVO } from '@/api/wms/md/item/category'
|
||||||
|
|
||||||
|
/** WMS 商品分类选择器 */
|
||||||
|
defineOptions({ name: 'WmsItemCategorySelect', inheritAttrs: false })
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
modelValue?: number
|
||||||
|
disabled?: boolean
|
||||||
|
placeholder?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
disabled: false,
|
||||||
|
placeholder: '请选择商品分类'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: number | undefined]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const categoryTree = ref<ItemCategoryVO[]>([]) // 分类树
|
||||||
|
|
||||||
|
const selectValue = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 获得分类树 */
|
||||||
|
const getCategoryTree = async () => {
|
||||||
|
const data = await ItemCategoryApi.getItemCategorySimpleList()
|
||||||
|
categoryTree.value = handleTree(data, 'id', 'parentId')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
await getCategoryTree()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<!-- WMS 商品分类树组件 -->
|
||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<el-input v-model="filterText" class="p-[15px]" clearable :placeholder="filterPlaceholder">
|
||||||
|
<template #prefix>
|
||||||
|
<Icon icon="ep:search" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<el-scrollbar class="!h-[calc(100%-32px-30px)]">
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
:data="categoryList"
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
:filter-node-method="filterNode"
|
||||||
|
:props="defaultProps"
|
||||||
|
default-expand-all
|
||||||
|
highlight-current
|
||||||
|
node-key="id"
|
||||||
|
@node-click="handleNodeClick"
|
||||||
|
/>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElTree } from 'element-plus'
|
||||||
|
import { defaultProps, handleTree } from '@/utils/tree'
|
||||||
|
import { ItemCategoryApi, ItemCategoryVO } from '@/api/wms/md/item/category'
|
||||||
|
|
||||||
|
/** WMS 商品分类树组件 */
|
||||||
|
defineOptions({ name: 'WmsItemCategoryTree' })
|
||||||
|
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
filterPlaceholder?: string // 搜索输入框占位文字
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
filterPlaceholder: '请输入分类名称'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'node-click': [categoryId: number | undefined]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const filterText = ref('') // 过滤关键字
|
||||||
|
const categoryList = ref<ItemCategoryVO[]>([]) // 分类树数据
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>() // 树 Ref
|
||||||
|
let currentNodeId: number | null = null // 当前选中的节点 ID
|
||||||
|
|
||||||
|
/** 加载分类树 */
|
||||||
|
const loadTree = async () => {
|
||||||
|
const data = await ItemCategoryApi.getItemCategorySimpleList()
|
||||||
|
categoryList.value = handleTree(data, 'id', 'parentId')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 基于名字过滤 */
|
||||||
|
const filterNode = (name: string, data: ItemCategoryVO) => {
|
||||||
|
if (!name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return !!data.name?.includes(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 监听过滤关键字 */
|
||||||
|
watch(filterText, (val) => {
|
||||||
|
treeRef.value?.filter(val)
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 处理节点点击:支持点击同一节点取消选中 */
|
||||||
|
const handleNodeClick = (row: ItemCategoryVO) => {
|
||||||
|
if (currentNodeId === row.id) {
|
||||||
|
treeRef.value?.setCurrentKey(undefined)
|
||||||
|
currentNodeId = null
|
||||||
|
emit('node-click', undefined)
|
||||||
|
} else {
|
||||||
|
currentNodeId = row.id!
|
||||||
|
emit('node-click', row.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 清空选中状态 */
|
||||||
|
const reset = () => {
|
||||||
|
currentNodeId = null
|
||||||
|
filterText.value = ''
|
||||||
|
treeRef.value?.setCurrentKey(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设置当前选中分类 */
|
||||||
|
const setCurrent = (categoryId: number) => {
|
||||||
|
treeRef.value?.setCurrentKey(categoryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ reset, setCurrent })
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadTree()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,312 @@
|
||||||
|
<!-- WMS 商品管理 -->
|
||||||
|
<template>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="4" :xs="24">
|
||||||
|
<ContentWrap class="h-1/1">
|
||||||
|
<ItemCategoryTree ref="categoryTreeRef" @node-click="handleCategoryNodeClick" />
|
||||||
|
</ContentWrap>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="20" :xs="24">
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-form
|
||||||
|
ref="queryFormRef"
|
||||||
|
:inline="true"
|
||||||
|
:model="queryParams"
|
||||||
|
class="-mb-15px"
|
||||||
|
label-width="68px"
|
||||||
|
>
|
||||||
|
<el-form-item label="商品编号" prop="code">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.code"
|
||||||
|
class="!w-240px"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入商品编号"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品名称" prop="name">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.name"
|
||||||
|
class="!w-240px"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入商品名称"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品品牌" prop="brandId">
|
||||||
|
<ItemBrandSelect v-model="queryParams.brandId" class="!w-240px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="handleQuery">
|
||||||
|
<Icon class="mr-5px" icon="ep:search" />
|
||||||
|
搜索
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="resetQuery">
|
||||||
|
<Icon class="mr-5px" icon="ep:refresh" />
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['wms:item:create']"
|
||||||
|
plain
|
||||||
|
type="primary"
|
||||||
|
@click="openForm('create')"
|
||||||
|
>
|
||||||
|
<Icon class="mr-5px" icon="ep:plus" />
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['wms:item:export']"
|
||||||
|
:loading="exportLoading"
|
||||||
|
plain
|
||||||
|
type="success"
|
||||||
|
@click="handleExport"
|
||||||
|
>
|
||||||
|
<Icon class="mr-5px" icon="ep:download" />
|
||||||
|
导出
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<!-- 商品列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
:data="list"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
:span-method="spanMethod"
|
||||||
|
>
|
||||||
|
<el-table-column label="商品信息" min-width="220">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="text-14px">{{ scope.row.itemName }}</div>
|
||||||
|
<div v-if="scope.row.itemCode" class="text-12px text-gray-500">
|
||||||
|
{{ scope.row.itemCode }}
|
||||||
|
</div>
|
||||||
|
<div v-if="scope.row.brandName" class="text-12px text-gray-500">
|
||||||
|
品牌:{{ scope.row.brandName }}
|
||||||
|
</div>
|
||||||
|
<div v-if="scope.row.categoryName" class="text-12px text-gray-500">
|
||||||
|
分类:{{ scope.row.categoryName }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="规格信息" min-width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="text-14px">{{ scope.row.name }}</div>
|
||||||
|
<div v-if="scope.row.code" class="text-12px text-gray-500"
|
||||||
|
>编号:{{ scope.row.code }}</div
|
||||||
|
>
|
||||||
|
<div v-if="scope.row.barCode" class="text-12px text-gray-500">
|
||||||
|
条码:{{ scope.row.barCode }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="金额(元)" min-width="140">
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="hasValue(scope.row.costPrice)">
|
||||||
|
成本价:{{ formatPrice(scope.row.costPrice) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="hasValue(scope.row.sellingPrice)">
|
||||||
|
销售价:{{ formatPrice(scope.row.sellingPrice) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="重量(kg)" min-width="140">
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="hasValue(scope.row.netWeight)">
|
||||||
|
净重:{{ formatWeight(scope.row.netWeight) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="hasValue(scope.row.grossWeight)">
|
||||||
|
毛重:{{ formatWeight(scope.row.grossWeight) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="right" label="长宽高(cm)" min-width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatDimensionText(scope.row.length, scope.row.width, scope.row.height) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="操作" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['wms:item:update']"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
@click="openForm('update', scope.row.itemId)"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['wms:item:delete']"
|
||||||
|
link
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope.row.itemId, scope.row.itemName)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNo"
|
||||||
|
:total="total"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
</ContentWrap>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
<ItemForm ref="formRef" @success="getList" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import download from '@/utils/download'
|
||||||
|
import { ItemApi, ItemVO } from '@/api/wms/md/item'
|
||||||
|
import { ItemSkuVO } from '@/api/wms/md/item/sku'
|
||||||
|
import ItemForm from './ItemForm.vue'
|
||||||
|
import ItemCategoryTree from './category/components/ItemCategoryTree.vue'
|
||||||
|
import ItemBrandSelect from './brand/components/ItemBrandSelect.vue'
|
||||||
|
import { isNullOrUnDef } from '@/utils/is'
|
||||||
|
import { formatDimensionText, formatPrice, formatWeight } from '@/views/wms/utils/format'
|
||||||
|
|
||||||
|
/** WMS 商品管理 */
|
||||||
|
defineOptions({ name: 'WmsItem' })
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中
|
||||||
|
const list = ref<ItemSkuVO[]>([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const queryParams = reactive<{
|
||||||
|
pageNo: number
|
||||||
|
pageSize: number
|
||||||
|
code?: string
|
||||||
|
name?: string
|
||||||
|
categoryId?: number
|
||||||
|
brandId?: number
|
||||||
|
}>({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
code: undefined,
|
||||||
|
name: undefined,
|
||||||
|
categoryId: undefined,
|
||||||
|
brandId: undefined
|
||||||
|
})
|
||||||
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
const categoryTreeRef = ref() // 分类树
|
||||||
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
const hasValue = (value?: number | string | null) => !isNullOrUnDef(value)
|
||||||
|
|
||||||
|
/** 查询商品列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await ItemApi.getItemPage(queryParams)
|
||||||
|
list.value = buildItemSkuRows(data.list || [])
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开商品 SKU 列表 */
|
||||||
|
const buildItemSkuRows = (items: ItemVO[]) => {
|
||||||
|
return items.flatMap((item) => {
|
||||||
|
const skus = item.skus?.length ? item.skus : [{}]
|
||||||
|
return skus.map((sku) => ({
|
||||||
|
...sku,
|
||||||
|
itemId: item.id,
|
||||||
|
itemCode: item.code,
|
||||||
|
itemName: item.name,
|
||||||
|
categoryId: item.categoryId,
|
||||||
|
categoryName: item.categoryName,
|
||||||
|
unit: item.unit,
|
||||||
|
brandId: item.brandId,
|
||||||
|
brandName: item.brandName
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value.resetFields()
|
||||||
|
categoryTreeRef.value?.reset()
|
||||||
|
queryParams.categoryId = undefined
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分类树点击 */
|
||||||
|
const handleCategoryNodeClick = (categoryId: number | undefined) => {
|
||||||
|
queryParams.categoryId = categoryId
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加/修改操作 */
|
||||||
|
const formRef = ref()
|
||||||
|
const openForm = (type: string, id?: number) => {
|
||||||
|
formRef.value.open(type, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品 */
|
||||||
|
const handleDelete = async (id: number, name?: string) => {
|
||||||
|
try {
|
||||||
|
// 删除的二次确认
|
||||||
|
await message.confirm('确认删除商品【' + name + '】吗?')
|
||||||
|
// 发起删除
|
||||||
|
await ItemApi.deleteItem(id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
// 刷新列表
|
||||||
|
await getList()
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
// 导出的二次确认
|
||||||
|
await message.exportConfirm()
|
||||||
|
// 发起导出
|
||||||
|
exportLoading.value = true
|
||||||
|
const data = await ItemApi.exportItem(queryParams)
|
||||||
|
download.excel(data, '商品.xls')
|
||||||
|
} catch {
|
||||||
|
} finally {
|
||||||
|
exportLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 合并商品维度的重复单元格 */
|
||||||
|
const spanMethod = ({ rowIndex, columnIndex }: { rowIndex: number; columnIndex: number }) => {
|
||||||
|
if (![0, 5].includes(columnIndex)) {
|
||||||
|
return { rowspan: 1, colspan: 1 }
|
||||||
|
}
|
||||||
|
const row = list.value[rowIndex]
|
||||||
|
if (rowIndex > 0 && list.value[rowIndex - 1]?.itemId === row.itemId) {
|
||||||
|
return { rowspan: 0, colspan: 0 }
|
||||||
|
}
|
||||||
|
let rowspan = 1
|
||||||
|
for (let index = rowIndex + 1; index < list.value.length; index++) {
|
||||||
|
if (list.value[index]?.itemId !== row.itemId) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
rowspan++
|
||||||
|
}
|
||||||
|
return { rowspan, colspan: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
await getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -15,7 +15,12 @@
|
||||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入仓库编号" />
|
<el-input v-model="formData.code" maxlength="20" placeholder="请输入仓库编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="排序" prop="sort">
|
<el-form-item label="排序" prop="sort">
|
||||||
<el-input-number v-model="formData.sort" :min="0" class="!w-1/1" controls-position="right" />
|
<el-input-number
|
||||||
|
v-model="formData.sort"
|
||||||
|
:min="0"
|
||||||
|
class="!w-1/1"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,9 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
const warehouseList = ref<WarehouseVO[]>([]) // 仓库精简列表
|
const warehouseList = ref<WarehouseVO[]>([]) // 仓库精简列表
|
||||||
const selectableWarehouseList = computed(() =>
|
const selectableWarehouseList = computed(() =>
|
||||||
warehouseList.value.filter((warehouse): warehouse is WarehouseVO & { id: number } => !!warehouse.id)
|
warehouseList.value.filter(
|
||||||
|
(warehouse): warehouse is WarehouseVO & { id: number } => !!warehouse.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const formData = ref<WarehouseAreaVO>({
|
const formData = ref<WarehouseAreaVO>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,9 @@ const queryFormRef = ref() // 搜索的表单
|
||||||
const exportLoading = ref(false) // 导出的加载中
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
const warehouseList = ref<WarehouseVO[]>([]) // 仓库精简列表
|
const warehouseList = ref<WarehouseVO[]>([]) // 仓库精简列表
|
||||||
const selectableWarehouseList = computed(() =>
|
const selectableWarehouseList = computed(() =>
|
||||||
warehouseList.value.filter((warehouse): warehouse is WarehouseVO & { id: number } => !!warehouse.id)
|
warehouseList.value.filter(
|
||||||
|
(warehouse): warehouse is WarehouseVO & { id: number } => !!warehouse.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 查询库区列表 */
|
/** 查询库区列表 */
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,9 @@
|
||||||
v-if="AREA_ENABLE"
|
v-if="AREA_ENABLE"
|
||||||
:to="{ name: 'WmsWarehouseArea', params: { warehouseId: scope.row.id } }"
|
:to="{ name: 'WmsWarehouseArea', params: { warehouseId: scope.row.id } }"
|
||||||
>
|
>
|
||||||
<el-button v-hasPermi="['wms:warehouse-area:query']" link type="primary">库区</el-button>
|
<el-button v-hasPermi="['wms:warehouse-area:query']" link type="primary">
|
||||||
|
库区
|
||||||
|
</el-button>
|
||||||
</router-link>
|
</router-link>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPermi="['wms:warehouse:update']"
|
v-hasPermi="['wms:warehouse:update']"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* WMS 展示格式化和表单配置
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { isNullOrUnDef } from '@/utils/is'
|
||||||
|
|
||||||
|
/** 金额小数位 */
|
||||||
|
export const PRICE_PRECISION = 2
|
||||||
|
/** 重量小数位 */
|
||||||
|
export const WEIGHT_PRECISION = 3
|
||||||
|
/** 长宽高小数位 */
|
||||||
|
export const DIMENSION_PRECISION = 1
|
||||||
|
|
||||||
|
export const formatNumber = (
|
||||||
|
value?: number | string | null,
|
||||||
|
digit: number = PRICE_PRECISION
|
||||||
|
) => {
|
||||||
|
if (isNullOrUnDef(value)) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
if (typeof value === 'string' && value.trim() === '') {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const numberValue = typeof value === 'string' ? Number(value) : value
|
||||||
|
if (!Number.isFinite(numberValue)) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return numberValue.toFixed(digit)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 格式化金额,保留 2 位小数 */
|
||||||
|
export const formatPrice = (value?: number | string | null) => {
|
||||||
|
return formatNumber(value, PRICE_PRECISION)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 格式化重量,保留 3 位小数 */
|
||||||
|
export const formatWeight = (value?: number | string | null) => {
|
||||||
|
return formatNumber(value, WEIGHT_PRECISION)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 格式化长宽高,保留 1 位小数 */
|
||||||
|
export const formatDimension = (value?: number | string | null) => {
|
||||||
|
return formatNumber(value, DIMENSION_PRECISION)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 格式化长宽高组合,保留 1 位小数 */
|
||||||
|
export const formatDimensionText = (
|
||||||
|
length?: number | string | null,
|
||||||
|
width?: number | string | null,
|
||||||
|
height?: number | string | null
|
||||||
|
) => {
|
||||||
|
if (!isNullOrUnDef(length) && !isNullOrUnDef(width) && !isNullOrUnDef(height)) {
|
||||||
|
return [formatDimension(length), formatDimension(width), formatDimension(height)].join(' * ')
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
!isNullOrUnDef(length) ? `长:${formatDimension(length)}` : undefined,
|
||||||
|
!isNullOrUnDef(width) ? `宽:${formatDimension(width)}` : undefined,
|
||||||
|
!isNullOrUnDef(height) ? `高:${formatDimension(height)}` : undefined
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue