Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
factory_front
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
qinjianhui
factory_front
Commits
dbaa0fee
Commit
dbaa0fee
authored
Jun 29, 2026
by
qinjianhui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 共享库存表格、新增页面
parent
0b8a1459
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
541 additions
and
4 deletions
+541
-4
src/api/warehouse/warehouseRuleSetting.ts
+13
-0
src/components/TableView.vue
+1
-1
src/types/api/warehouse/warehouseRuleSetting.ts
+28
-0
src/types/table.d.ts
+2
-2
src/views/warehouse/warehouseRuleSetting/components/EditDialog.vue
+246
-0
src/views/warehouse/warehouseRuleSetting/hooks/useWarehouseRuleSettingTableColumns.tsx
+99
-0
src/views/warehouse/warehouseRuleSetting/index.vue
+152
-1
No files found.
src/api/warehouse/warehouseRuleSetting.ts
0 → 100644
View file @
dbaa0fee
import
{
BasePaginationData
}
from
'@/types/api'
import
axios
from
'../axios'
import
{
SearchForm
,
WarehouseRuleSettingData
}
from
'@/types/api/warehouse/warehouseRuleSetting'
export
function
getWarehouseRuleSettingListApi
(
data
:
SearchForm
,
page
:
number
,
pageSize
:
number
,
)
{
return
axios
.
post
<
never
,
BasePaginationData
<
WarehouseRuleSettingData
>>
(
'warehouseRuleSetting/list_page'
,
{
...
data
,
page
,
pageSize
},
)
}
src/components/TableView.vue
View file @
dbaa0fee
...
@@ -32,7 +32,7 @@
...
@@ -32,7 +32,7 @@
align=
"center"
align=
"center"
:class=
"isMore ? 'is-more-active' : ''"
:class=
"isMore ? 'is-more-active' : ''"
></ElTableColumn>
></ElTableColumn>
<template
v-for=
"column in columns"
:key=
"column.
key
"
>
<template
v-for=
"column in columns"
:key=
"column.
prop
"
>
<ElTableColumn
<ElTableColumn
v-if=
"column.type === 'expand'"
v-if=
"column.type === 'expand'"
v-bind=
"column"
v-bind=
"column"
...
...
src/types/api/warehouse/warehouseRuleSetting.ts
0 → 100644
View file @
dbaa0fee
export
interface
SearchForm
{
startTime
:
string
endTime
:
string
warehouseSku
:
string
warehouseGroupName
:
string
status
:
number
}
export
interface
WarehouseRuleSettingData
{
id
?:
number
createTime
?:
string
warehouseSku
?:
string
warehouseGroupName
?:
string
status
?:
number
}
export
interface
WarehouseRuleSpuItem
{
warehouseSpu
:
string
productName
:
string
spuImage
?:
string
sortNo
:
number
}
export
interface
EditForm
{
id
?:
number
warehouseGroupName
?:
string
status
?:
number
spuList
?:
WarehouseRuleSpuItem
[]
}
src/types/table.d.ts
View file @
dbaa0fee
import
type
{
Column
as
ElColumn
}
from
'element-plus/lib/components/index.js'
import
type
{
Column
as
ElColumn
}
from
'element-plus/lib/components/index.js'
import
type
{
VNode
}
from
'vue'
interface
Column
<
D
>
extends
Omit
<
ElColumn
,
'width'
>
{
interface
Column
<
D
>
extends
Omit
<
ElColumn
,
'width'
>
{
/** 为 false 时隐藏该列;未设置时默认显示 */
/** 为 false 时隐藏该列;未设置时默认显示 */
showColumn
?:
boolean
showColumn
?:
boolean
width
?:
number
|
string
width
?:
number
|
string
minWidth
?:
number
|
string
minWidth
?:
number
|
string
key
?:
string
slot
?:
string
slot
?:
string
headerSlot
?:
string
headerSlot
?:
string
headerRender
?:
(
scope
:
{
column
:
never
;
index
:
number
})
=>
JSX
.
Element
headerRender
?:
(
scope
:
{
column
:
never
;
index
:
number
})
=>
JSX
.
Element
render
?:
(
scope
:
{
row
:
D
;
index
:
number
})
=>
JSX
.
Element
render
?:
(
row
:
D
,
index
:
number
)
=>
VNode
|
JSX
.
Element
formatDate
?:
(
row
:
D
)
=>
string
formatDate
?:
(
row
:
D
)
=>
string
children
?:
Column
<
D
>
[]
children
?:
Column
<
D
>
[]
subs
?:
Column
<
D
>
[]
subs
?:
Column
<
D
>
[]
...
...
src/views/warehouse/warehouseRuleSetting/components/EditDialog.vue
0 → 100644
View file @
dbaa0fee
<
template
>
<ElDialog
v-model=
"dialogVisible"
:title=
"editForm.id ? '编辑共享库存组' : '新增共享库存组'"
width=
"800px"
:close-on-click-modal=
"false"
destroy-on-close
>
<ElForm
ref=
"editFormRef"
:model=
"editForm"
label-width=
"100px"
>
<div
class=
"section-title"
>
分组基础信息
</div>
<ElFormItem
label=
"库存组名称"
prop=
"warehouseGroupName"
:rules=
"[
{ required: true, message: '请输入库存组名称', trigger: 'blur' },
]"
>
<ElInput
v-model=
"editForm.warehouseGroupName"
clearable
placeholder=
"请输入库存组名称"
style=
"width: 100%"
/>
</ElFormItem>
<ElFormItem
label=
"状态"
prop=
"status"
:rules=
"[
{ required: true, message: '请选择状态', trigger: 'blur' }]"
>
<ElSwitch
v-model=
"editForm.status"
:active-value=
"1"
:inactive-value=
"0"
style=
"--el-switch-on-color: #42b983"
/>
</ElFormItem>
<div
class=
"section-title"
>
组内SPU清单
</div>
<div
class=
"spu-search-bar"
>
<ElInput
v-model=
"spuSearchKeyword"
clearable
placeholder=
"请输入库存SPU"
style=
"width: 200px"
@
keyup
.
enter=
"handleSearchSpu"
/>
<ElButton
type=
"primary"
@
click=
"handleSearchSpu"
>
查询
</ElButton>
</div>
<div
class=
"spu-drag-tip"
>
<el-icon
style=
"color: #409eff; font-size: 16px"
><Warning
/></el-icon
><span>
拖动SPU调整扣减顺序
</span>
</div>
<div
class=
"spu-table-wrapper"
>
<TableView
:paginated-data=
"editForm.spuList ?? []"
:columns=
"spuTableColumns"
row-key=
"warehouseSpu"
size=
"small"
>
<template
#
sortNo=
"
{ row, index }">
<span
class=
"drag-handle"
draggable=
"true"
@
dragstart=
"handleDragStart(index)"
@
dragover
.
prevent
@
drop=
"handleDrop(index)"
>
{{
row
.
sortNo
}}
</span>
</
template
>
<
template
#
spuImage=
"{ row }"
>
<ImageView
:src=
"row.spuImage"
width=
"40px"
height=
"40px"
/>
</
template
>
<
template
#
operation=
"{ index }"
>
<ElButton
link
type=
"danger"
@
click=
"handleRemoveSpu(index)"
>
删除
</ElButton>
</
template
>
</TableView>
</div>
</ElForm>
<
template
#
footer
>
<div
class=
"dialog-footer"
>
<ElButton
@
click=
"handleCancel"
>
取消
</ElButton>
<ElButton
type=
"primary"
:loading=
"saving"
@
click=
"handleSave"
>
保存
</ElButton>
</div>
</
template
>
</ElDialog>
</template>
<
script
setup
lang=
"ts"
>
import
ImageView
from
'@/components/ImageView.vue'
import
TableView
from
'@/components/TableView.vue'
import
{
EditForm
,
WarehouseRuleSpuItem
,
}
from
'@/types/api/warehouse/warehouseRuleSetting'
import
{
Warning
}
from
'@element-plus/icons-vue'
import
{
useWarehouseRuleSettingTableColumns
}
from
'../hooks/useWarehouseRuleSettingTableColumns'
const
emit
=
defineEmits
<
{
(
e
:
'update:visible'
,
value
:
boolean
):
void
(
e
:
'saved'
):
void
}
>
()
const
props
=
defineProps
<
{
visible
:
boolean
}
>
()
const
dialogVisible
=
computed
({
get
()
{
return
props
.
visible
},
set
(
value
:
boolean
)
{
emit
(
'update:visible'
,
value
)
},
})
const
createDefaultForm
=
():
EditForm
=>
({
id
:
undefined
,
warehouseGroupName
:
''
,
status
:
1
,
spuList
:
[],
})
const
editForm
=
ref
<
EditForm
>
(
createDefaultForm
())
const
editFormRef
=
ref
()
const
spuSearchKeyword
=
ref
(
''
)
const
saving
=
ref
(
false
)
const
dragIndex
=
ref
<
number
|
null
>
(
null
)
const
{
spuTableColumns
}
=
useWarehouseRuleSettingTableColumns
()
const
resetFields
=
()
=>
{
editForm
.
value
=
createDefaultForm
()
spuSearchKeyword
.
value
=
''
dragIndex
.
value
=
null
nextTick
(()
=>
{
editFormRef
.
value
?.
clearValidate
()
})
}
const
updateSortNo
=
(
list
:
WarehouseRuleSpuItem
[])
=>
{
return
list
.
map
((
item
,
index
)
=>
({
...
item
,
sortNo
:
index
+
1
,
}))
}
const
handleDragStart
=
(
index
:
number
)
=>
{
dragIndex
.
value
=
index
}
const
handleDrop
=
(
index
:
number
)
=>
{
if
(
dragIndex
.
value
===
null
||
dragIndex
.
value
===
index
)
{
return
}
const
list
=
[...(
editForm
.
value
.
spuList
??
[])]
const
[
movedItem
]
=
list
.
splice
(
dragIndex
.
value
,
1
)
list
.
splice
(
index
,
0
,
movedItem
)
editForm
.
value
.
spuList
=
updateSortNo
(
list
)
dragIndex
.
value
=
null
}
const
handleSearchSpu
=
()
=>
{
// TODO: 调用接口查询库存SPU并添加到列表
}
const
handleRemoveSpu
=
(
index
:
number
)
=>
{
const
list
=
[...(
editForm
.
value
.
spuList
??
[])]
list
.
splice
(
index
,
1
)
editForm
.
value
.
spuList
=
updateSortNo
(
list
)
}
const
handleCancel
=
()
=>
{
dialogVisible
.
value
=
false
}
const
handleSave
=
async
()
=>
{
const
valid
=
await
editFormRef
.
value
?.
validate
().
catch
(()
=>
false
)
if
(
!
valid
)
{
return
}
saving
.
value
=
true
try
{
// TODO: 调用保存接口
emit
(
'saved'
)
dialogVisible
.
value
=
false
}
finally
{
saving
.
value
=
false
}
}
defineExpose
({
resetFields
,
})
</
script
>
<
style
scoped
lang=
"scss"
>
.section-title
{
font-size
:
14px
;
font-weight
:
600
;
color
:
#303133
;
margin-bottom
:
12px
;
padding-left
:
8px
;
border-left
:
3px
solid
#409eff
;
&
+
.el-form-item
{
margin-top
:
0
;
}
&
:not
(
:first-child
)
{
margin-top
:
8px
;
}
}
.spu-search-bar
{
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
margin-bottom
:
8px
;
}
.spu-drag-tip
{
font-size
:
12px
;
color
:
#909399
;
margin-bottom
:
8px
;
display
:
flex
;
align-items
:
center
;
gap
:
4px
;
}
.spu-table-wrapper
{
height
:
280px
;
}
.drag-handle
{
display
:
inline-block
;
width
:
100%
;
cursor
:
move
;
user-select
:
none
;
}
.dialog-footer
{
display
:
flex
;
justify-content
:
center
;
gap
:
10px
;
}
</
style
>
src/views/warehouse/warehouseRuleSetting/hooks/useWarehouseRuleSettingTableColumns.tsx
0 → 100644
View file @
dbaa0fee
import
{
ElButton
,
ElTag
}
from
'element-plus'
import
type
{
WarehouseRuleSettingData
}
from
'@/types/api/warehouse/warehouseRuleSetting'
const
statusMap
:
Record
<
number
,
{
label
:
string
;
type
:
'success'
|
'info'
}
>
=
{
1
:
{
label
:
'启用'
,
type
:
'success'
},
0
:
{
label
:
'禁用'
,
type
:
'info'
},
}
export
interface
UseWarehouseRuleSettingTableColumnsOptions
{
onEdit
?:
(
row
:
WarehouseRuleSettingData
)
=>
void
}
export
function
useWarehouseRuleSettingTableColumns
(
options
:
UseWarehouseRuleSettingTableColumnsOptions
=
{},
)
{
const
columns
=
computed
(()
=>
[
{
label
:
'库存组名称'
,
prop
:
''
,
align
:
'left'
,
},
{
label
:
'共享库存SPU'
,
prop
:
''
,
align
:
'left'
,
},
{
label
:
'创建时间'
,
prop
:
'createTime'
,
width
:
180
,
align
:
'center'
,
},
{
label
:
'状态'
,
prop
:
'status'
,
width
:
100
,
align
:
'center'
,
render
:
(
row
:
WarehouseRuleSettingData
)
=>
{
const
status
=
statusMap
[
row
.
status
??
-
1
]
return
status
?
(
<
ElTag
type=
{
status
.
type
}
>
{
status
.
label
}
</
ElTag
>
)
:
(
<
span
>
-
</
span
>
)
},
},
{
label
:
'操作'
,
width
:
100
,
align
:
'center'
,
render
:
(
row
:
WarehouseRuleSettingData
)
=>
{
return
(
<
div
>
<
ElButton
link
type=
"primary"
onClick=
{
()
=>
options
?.
onEdit
?.(
row
)
}
>
编辑
</
ElButton
>
</
div
>
)
},
},
])
const
spuTableColumns
=
computed
(()
=>
[
{
label
:
'扣减顺序'
,
width
:
90
,
align
:
'center'
,
slot
:
'sortNo'
,
},
{
label
:
'图片'
,
width
:
80
,
align
:
'center'
,
slot
:
'spuImage'
,
},
{
label
:
'库存SPU'
,
prop
:
'warehouseSpu'
,
minWidth
:
120
,
align
:
'left'
,
},
{
label
:
'商品名称'
,
prop
:
'productName'
,
minWidth
:
160
,
align
:
'left'
,
},
{
label
:
'操作'
,
width
:
80
,
align
:
'center'
,
slot
:
'operation'
,
},
])
return
{
columns
,
spuTableColumns
}
}
src/views/warehouse/warehouseRuleSetting/index.vue
View file @
dbaa0fee
...
@@ -11,15 +11,152 @@
...
@@ -11,15 +11,152 @@
</div>
</div>
<div
class=
"content-container flex-1 flex-column overflow-hidden"
>
<div
class=
"content-container flex-1 flex-column overflow-hidden"
>
主要内容
<div
class=
"search-form"
>
<ElForm
ref=
"searchFormRef"
:model=
"searchForm"
inline
>
<ElFormItem
label=
"创建时间"
>
<ElDatePicker
v-model=
"dateRange"
:default-time=
"[
new Date(0, 0, 0, 0, 0, 0),
new Date(0, 0, 0, 23, 59, 59),
]"
type=
"datetimerange"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
clearable
style=
"width: 260px"
format=
"YYYY-MM-DD HH:mm:ss"
value-format=
"YYYY-MM-DD HH:mm:ss"
/>
</ElFormItem>
<ElFormItem
label=
"库存SKU"
>
<ElInput
v-model=
"searchForm.warehouseSku"
clearable
placeholder=
"库存SKU"
style=
"width: 140px"
/>
</ElFormItem>
<ElFormItem
label=
"库存组名称"
>
<ElInput
v-model=
"searchForm.warehouseGroupName"
clearable
placeholder=
"库存组名称"
style=
"width: 140px"
/>
</ElFormItem>
<ElFormItem
label=
"状态"
><ElSelect
v-model=
"searchForm.status"
placeholder=
"请选择"
style=
"width: 140px"
>
<ElOption
label=
"启用"
:value=
"1"
/>
<ElOption
label=
"禁用"
:value=
"0"
/>
</ElSelect>
</ElFormItem>
<ElFormItem>
<ElButton
@
click=
"resetSearchForm"
>
重置
</ElButton>
</ElFormItem>
<ElFormItem>
<ElButton
type=
"primary"
@
click=
"search"
>
查询
</ElButton>
</ElFormItem>
<ElFormItem>
<ElButton
type=
"success"
@
click=
"() => handleEdit()"
>
新增
</ElButton>
</ElFormItem>
<ElFormItem>
<ElButton
type=
"danger"
>
删除
</ElButton>
</ElFormItem>
</ElForm>
</div>
<div
class=
"table-wrapper"
>
<TableView
serial-numberable
:selectionable=
"true"
:paginated-data=
"tableData"
:columns=
"tableColumns"
@
selection-change=
"handleSelectionChange"
/>
</div>
<div
class=
"table-pagination-bar"
>
<div
class=
"selected-count-text"
>
已选择
<strong
style=
"color: red"
>
{{
selectedRows
.
length
}}
</strong>
条数据
</div>
<ElPagination
v-model:current-page=
"currentPage"
v-model:page-size=
"pageSize"
:page-sizes=
"[100, 200, 300, 400, 500]"
background
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
style=
"margin: 0 auto"
@
current-change=
"handleCurrentChange"
@
size-change=
"handleSizeChange"
/>
</div>
</div>
</div>
</div>
</div>
<EditFormDialog
ref=
"editFormRef"
v-model:visible=
"editDialogVisible"
/>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
getWarehouseRuleSettingListApi
}
from
'@/api/warehouse/warehouseRuleSetting'
import
{
SearchForm
,
WarehouseRuleSettingData
,
}
from
'@/types/api/warehouse/warehouseRuleSetting'
import
usePageList
from
'@/utils/hooks/usePageList'
import
{
useValue
}
from
'@/utils/hooks/useValue'
import
{
ElDatePicker
,
ElFormItem
}
from
'element-plus'
import
{
useWarehouseRuleSettingTableColumns
}
from
'./hooks/useWarehouseRuleSettingTableColumns'
import
EditFormDialog
from
'./components/EditDialog.vue'
const
[
searchForm
,
resetSearchForm
]
=
useValue
<
SearchForm
>
({
startTime
:
''
,
endTime
:
''
,
warehouseSku
:
''
,
warehouseGroupName
:
''
,
status
:
1
,
})
const
dateRange
=
ref
([])
const
currentStatus
=
ref
(
'sharedInventory'
)
const
currentStatus
=
ref
(
'sharedInventory'
)
const
editDialogVisible
=
ref
(
false
)
const
editFormRef
=
ref
()
const
handleStatusClick
=
(
status
:
string
)
=>
{
const
handleStatusClick
=
(
status
:
string
)
=>
{
currentStatus
.
value
=
status
currentStatus
.
value
=
status
}
}
const
{
currentPage
,
pageSize
,
total
,
data
:
tableData
,
refresh
:
search
,
onCurrentPageChange
:
handleCurrentChange
,
onPageSizeChange
:
handleSizeChange
,
}
=
usePageList
<
WarehouseRuleSettingData
>
({
query
:
(
page
,
pageSize
)
=>
getWarehouseRuleSettingListApi
(
searchForm
.
value
,
page
,
pageSize
).
then
(
(
res
)
=>
res
.
data
,
),
})
const
selectedRows
=
ref
<
WarehouseRuleSettingData
[]
>
([])
const
handleSelectionChange
=
(
selection
:
WarehouseRuleSettingData
[])
=>
{
selectedRows
.
value
=
selection
}
const
handleEdit
=
async
(
row
?:
WarehouseRuleSettingData
)
=>
{
if
(
row
)
{
// 调用接口,获取数据
}
else
{
await
editFormRef
.
value
.
resetFields
()
}
editDialogVisible
.
value
=
true
}
const
{
columns
:
tableColumns
}
=
useWarehouseRuleSettingTableColumns
({
onEdit
:
handleEdit
,
})
</
script
>
</
script
>
<
style
scoped
lang=
"scss"
>
<
style
scoped
lang=
"scss"
>
.status-container
{
.status-container
{
...
@@ -40,4 +177,18 @@ const handleStatusClick = (status: string) => {
...
@@ -40,4 +177,18 @@ const handleStatusClick = (status: string) => {
}
}
}
}
}
}
.table-wrapper
{
flex
:
1
;
overflow
:
hidden
;
}
.table-pagination-bar
{
margin-top
:
10px
;
display
:
flex
;
align-items
:
center
;
}
.selected-count-text
{
font-size
:
14px
;
color
:
#606266
;
white-space
:
nowrap
;
}
</
style
>
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment