feat(wms):增加 code 字段生成(从后端到前端),用户更可控
parent
5f944548a3
commit
d128df618e
|
|
@ -3,6 +3,7 @@ import request from '@/config/axios'
|
|||
// WMS 商品品牌 VO
|
||||
export interface ItemBrandVO {
|
||||
id?: number
|
||||
code?: string
|
||||
name?: string
|
||||
createTime?: Date
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import request from '@/config/axios'
|
|||
export interface ItemCategoryVO {
|
||||
id?: number
|
||||
parentId?: number
|
||||
code?: string
|
||||
name?: string
|
||||
sort?: number
|
||||
status?: number
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@
|
|||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品编号" prop="code">
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入商品编号" />
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入商品编号">
|
||||
<template #append>
|
||||
<el-button @click="formData.code = generateWmsCode('I')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
|
|
@ -68,15 +72,23 @@
|
|||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编号/条码" width="220">
|
||||
<el-table-column label="编号/条码" width="260">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.code" maxlength="64" class="!w-1/1" placeholder="编号" />
|
||||
<el-input v-model="scope.row.code" maxlength="64" class="!w-1/1" placeholder="编号">
|
||||
<template #append>
|
||||
<el-button @click="scope.row.code = generateWmsCode('S')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-model="scope.row.barCode"
|
||||
maxlength="64"
|
||||
class="!w-1/1 mt-5px"
|
||||
placeholder="条码为空时,提交后自动生成"
|
||||
/>
|
||||
placeholder="条码"
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="scope.row.barCode = generateWmsCode()">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="长/宽/高(cm)" width="210">
|
||||
|
|
@ -168,6 +180,7 @@ 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 { generateWmsCode } from '@/views/wms/utils/constants'
|
||||
import ItemBrandSelect from './brand/components/ItemBrandSelect.vue'
|
||||
import ItemCategorySelect from './category/components/ItemCategorySelect.vue'
|
||||
|
||||
|
|
@ -192,6 +205,7 @@ const formData = ref<ItemVO>({
|
|||
skus: []
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
code: [{ required: true, message: '商品编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '商品名称不能为空', trigger: 'blur' }],
|
||||
categoryId: [{ required: true, message: '商品分类不能为空', trigger: 'change' }],
|
||||
skus: [{ required: true, message: '至少包含一个商品规格', trigger: 'change' }]
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@
|
|||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="品牌编号" prop="code">
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入品牌编号">
|
||||
<template #append>
|
||||
<el-button @click="formData.code = generateWmsCode('B')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌名称" prop="name">
|
||||
<el-input v-model="formData.name" maxlength="30" placeholder="请输入品牌名称" />
|
||||
</el-form-item>
|
||||
|
|
@ -21,6 +28,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ItemBrandApi, ItemBrandVO } from '@/api/wms/md/item/brand'
|
||||
import { generateWmsCode } from '@/views/wms/utils/constants'
|
||||
|
||||
/** WMS 商品品牌表单 */
|
||||
defineOptions({ name: 'WmsItemBrandForm' })
|
||||
|
|
@ -34,9 +42,11 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
|
|||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref<ItemBrandVO>({
|
||||
id: undefined,
|
||||
code: undefined,
|
||||
name: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
code: [{ required: true, message: '品牌编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '品牌名称不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
|
@ -87,6 +97,7 @@ const submitForm = async () => {
|
|||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
code: undefined,
|
||||
name: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,15 @@
|
|||
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"
|
||||
|
|
@ -53,6 +62,7 @@
|
|||
<!-- 品牌列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table-column align="center" label="品牌编号" prop="code" width="160" />
|
||||
<el-table-column align="center" label="品牌名称" prop="name" />
|
||||
<el-table-column
|
||||
:formatter="dateFormatter"
|
||||
|
|
@ -113,6 +123,7 @@ const total = ref(0) // 列表的总页数
|
|||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
code: undefined,
|
||||
name: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
|
|
|||
|
|
@ -16,9 +16,15 @@
|
|||
check-strictly
|
||||
default-expand-all
|
||||
placeholder="请选择上级分类"
|
||||
value-key="categoryId"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类编号" prop="code">
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入分类编号">
|
||||
<template #append>
|
||||
<el-button @click="formData.code = generateWmsCode('C')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入分类名称" />
|
||||
</el-form-item>
|
||||
|
|
@ -53,6 +59,7 @@ import { defaultProps, handleTree } from '@/utils/tree'
|
|||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { ItemCategoryApi, ItemCategoryVO } from '@/api/wms/md/item/category'
|
||||
import { generateWmsCode } from '@/views/wms/utils/constants'
|
||||
|
||||
/** WMS 商品分类表单 */
|
||||
defineOptions({ name: 'WmsItemCategoryForm' })
|
||||
|
|
@ -67,12 +74,14 @@ const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|||
const formData = ref<ItemCategoryVO>({
|
||||
id: undefined,
|
||||
parentId: undefined,
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
sort: 0,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
parentId: [{ required: true, message: '上级分类不能为空', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '分类编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
||||
|
|
@ -140,6 +149,7 @@ const resetForm = (parentId?: number) => {
|
|||
formData.value = {
|
||||
id: undefined,
|
||||
parentId,
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
sort: 0,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
|
|
|
|||
|
|
@ -9,6 +9,15 @@
|
|||
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"
|
||||
|
|
@ -71,6 +80,7 @@
|
|||
row-key="id"
|
||||
>
|
||||
<el-table-column label="分类名称" prop="name" />
|
||||
<el-table-column align="center" label="分类编号" prop="code" width="160" />
|
||||
<el-table-column align="center" label="排序" prop="sort" width="120" />
|
||||
<el-table-column align="center" label="状态" prop="status" width="120">
|
||||
<template #default="scope">
|
||||
|
|
@ -137,6 +147,7 @@ const list = ref<ItemCategoryVO[]>([]) // 列表的数据
|
|||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
status: undefined
|
||||
})
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ const selectedList = ref<ItemSkuVO[]>([]) // 已选择 SKU 列表
|
|||
const selectedMap = ref<Map<number, ItemSkuVO>>(new Map()) // 跨页已选择 SKU
|
||||
const preSelectedIds = ref<number[]>([]) // 打开弹窗时传入的已选 SKU 编号
|
||||
const disabledSelectedIds = ref<Set<number>>(new Set()) // 已在业务明细中使用的 SKU 编号
|
||||
const multiple = ref(true) // 是否允许多选
|
||||
const preselectDisabled = ref(true) // 是否回显已禁用的 SKU
|
||||
const syncingSingleSelection = ref(false) // 单选模式同步表格勾选状态中
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>() // 表格 Ref
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const getDefaultQueryParams = () => ({
|
||||
|
|
@ -179,8 +182,13 @@ const emit = defineEmits<{
|
|||
}>()
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (selectedIds?: number[]) => {
|
||||
const open = async (
|
||||
selectedIds?: number[],
|
||||
options?: { multiple?: boolean; preselectDisabled?: boolean }
|
||||
) => {
|
||||
dialogVisible.value = true
|
||||
multiple.value = options?.multiple ?? true
|
||||
preselectDisabled.value = options?.preselectDisabled ?? true
|
||||
Object.assign(queryParams, getDefaultQueryParams())
|
||||
selectedList.value = []
|
||||
selectedMap.value = new Map()
|
||||
|
|
@ -219,7 +227,7 @@ const loadSkuList = async () => {
|
|||
|
||||
/** 初始化已选 SKU */
|
||||
const initSelectedList = () => {
|
||||
if (preSelectedIds.value.length === 0) {
|
||||
if (!preselectDisabled.value || preSelectedIds.value.length === 0) {
|
||||
return
|
||||
}
|
||||
allList.value.forEach((sku) => {
|
||||
|
|
@ -286,7 +294,34 @@ const isRowSelectable = (row: ItemSkuVO) => {
|
|||
}
|
||||
|
||||
/** 选择变化 */
|
||||
const handleSelectionChange = (rows: ItemSkuVO[]) => {
|
||||
const handleSelectionChange = async (rows: ItemSkuVO[]) => {
|
||||
if (syncingSingleSelection.value) {
|
||||
return
|
||||
}
|
||||
if (!multiple.value) {
|
||||
let row: ItemSkuVO | undefined
|
||||
for (let i = rows.length - 1; i >= 0; i--) {
|
||||
const item = rows[i]
|
||||
if (item.id && !disabledSelectedIds.value.has(item.id)) {
|
||||
row = item
|
||||
break
|
||||
}
|
||||
}
|
||||
selectedMap.value = new Map()
|
||||
if (row?.id) {
|
||||
selectedMap.value.set(row.id, row)
|
||||
}
|
||||
selectedList.value = Array.from(selectedMap.value.values())
|
||||
syncingSingleSelection.value = true
|
||||
await nextTick()
|
||||
tableRef.value?.clearSelection()
|
||||
if (row) {
|
||||
tableRef.value?.toggleRowSelection(row, true)
|
||||
}
|
||||
await nextTick()
|
||||
syncingSingleSelection.value = false
|
||||
return
|
||||
}
|
||||
const currentPageIds = list.value.map((row) => row.id).filter((id): id is number => !!id)
|
||||
currentPageIds.forEach((id) => {
|
||||
if (!disabledSelectedIds.value.has(id)) {
|
||||
|
|
@ -306,6 +341,11 @@ const handleRowDblClick = (row: ItemSkuVO) => {
|
|||
if (row.id && disabledSelectedIds.value.has(row.id)) {
|
||||
return
|
||||
}
|
||||
if (!multiple.value) {
|
||||
emit('change', [row])
|
||||
dialogVisible.value = false
|
||||
return
|
||||
}
|
||||
tableRef.value?.toggleRowSelection(row)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@
|
|||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="往来企业编号" prop="code">
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入往来企业编号" />
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入往来企业编号">
|
||||
<template #append>
|
||||
<el-button @click="formData.code = generateWmsCode('M')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
|
|
@ -88,6 +92,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { MerchantApi, MerchantVO } from '@/api/wms/md/merchant'
|
||||
import { generateWmsCode } from '@/views/wms/utils/constants'
|
||||
|
||||
/** WMS 往来企业表单 */
|
||||
defineOptions({ name: 'WmsMerchantForm' })
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
<el-input v-model="formData.name" maxlength="50" placeholder="请输入仓库名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库编号" prop="code">
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入仓库编号" />
|
||||
<el-input v-model="formData.code" maxlength="20" placeholder="请输入仓库编号">
|
||||
<template #append>
|
||||
<el-button @click="formData.code = generateWmsCode('W')">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number
|
||||
|
|
@ -40,6 +44,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { WarehouseApi, WarehouseVO } from '@/api/wms/md/warehouse'
|
||||
import { generateWmsCode } from '@/views/wms/utils/constants'
|
||||
|
||||
/** WMS 仓库表单 */
|
||||
defineOptions({ name: 'WmsWarehouseForm' })
|
||||
|
|
|
|||
|
|
@ -29,3 +29,24 @@ export const CustomerMerchantTypeList = [
|
|||
MerchantTypeEnum.CUSTOMER,
|
||||
MerchantTypeEnum.CUSTOMER_SUPPLIER
|
||||
]
|
||||
|
||||
/**
|
||||
* 生成 WMS 编号 / 条码。
|
||||
*
|
||||
* @param prefix 可选前缀,按业务域区分编号种类:
|
||||
* - `I` 商品编号
|
||||
* - `S` SKU 编号
|
||||
* - `W` 仓库编号
|
||||
* - `M` 往来企业编号
|
||||
* - 不传 / 空串 用于 SKU 条码(条码业务习惯纯数字)
|
||||
* @returns 前缀 + 8 位随机数字串。
|
||||
*
|
||||
* 由前端在表单【生成】按钮上调用,避免后端兜底生成造成编号不可控。
|
||||
*/
|
||||
export const generateWmsCode = (prefix: string = ''): string => {
|
||||
let result = ''
|
||||
for (let i = 0; i < 8; i++) {
|
||||
result += Math.floor(Math.random() * 10).toString()
|
||||
}
|
||||
return prefix + result
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue