Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1bb9df7b
authored
Nov 21, 2023
by
owen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
商品中心:修复商品表格选择对话框,在多选时表头内的多选框不显示选中效果的问题
parent
e0a731dd
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
130 additions
and
76 deletions
+130
-76
src/views/mall/product/spu/components/SpuShowcase.vue
+3
-3
src/views/mall/product/spu/components/SpuTableSelect.vue
+127
-73
No files found.
src/views/mall/product/spu/components/SpuShowcase.vue
View file @
1bb9df7b
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
</el-tooltip>
</el-tooltip>
</div>
</div>
<!-- 商品选择对话框(表格形式) -->
<!-- 商品选择对话框(表格形式) -->
<SpuTableSelect
ref=
"spuTableSelectRef"
multiple
@
change=
"handleSpuSelected"
/>
<SpuTableSelect
ref=
"spuTableSelectRef"
:multiple=
"limit != 1"
@
change=
"handleSpuSelected"
/>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
...
@@ -88,8 +88,8 @@ const openSpuTableSelect = () => {
...
@@ -88,8 +88,8 @@ const openSpuTableSelect = () => {
* 选择商品后触发
* 选择商品后触发
* @param spus 选中的商品列表
* @param spus 选中的商品列表
*/
*/
const
handleSpuSelected
=
(
spus
:
ProductSpuApi
.
Spu
[])
=>
{
const
handleSpuSelected
=
(
spus
:
ProductSpuApi
.
Spu
|
ProductSpuApi
.
Spu
[])
=>
{
productSpus
.
value
=
spus
productSpus
.
value
=
isArray
(
spus
)
?
spus
:
[
spus
]
emitSpuChange
()
emitSpuChange
()
}
}
...
...
src/views/mall/product/spu/components/SpuTableSelect.vue
View file @
1bb9df7b
<
template
>
<
template
>
<Dialog
v-model=
"dialogVisible"
:appendToBody=
"true"
title=
"选择商品"
width=
"70%"
>
<Dialog
v-model=
"dialogVisible"
:appendToBody=
"true"
title=
"选择商品"
width=
"70%"
>
<ContentWrap>
<ContentWrap>
<el-row
:gutter=
"20"
class=
"mb-10px"
>
<el-form
<el-col
:span=
"6"
>
ref=
"queryFormRef"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"68px"
>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
<el-input
v-model=
"queryParams.name"
v-model=
"queryParams.name"
class=
"!w-240px"
class=
"!w-240px"
...
@@ -10,19 +16,19 @@
...
@@ -10,19 +16,19 @@
placeholder=
"请输入商品名称"
placeholder=
"请输入商品名称"
@
keyup
.
enter=
"handleQuery"
@
keyup
.
enter=
"handleQuery"
/>
/>
</el-
col
>
</el-
form-item
>
<el-
col
:span=
"6
"
>
<el-
form-item
label=
"商品分类"
prop=
"categoryId
"
>
<el-tree-select
<el-tree-select
v-model=
"queryParams.categoryId"
v-model=
"queryParams.categoryId"
:data=
"categoryTreeList"
:data=
"categoryTreeList"
:props=
"defaultProps"
:props=
"defaultProps"
check-strictly
check-strictly
class=
"
w-1/1
"
class=
"
!w-240px
"
node-key=
"id"
node-key=
"id"
placeholder=
"请选择商品分类"
placeholder=
"请选择商品分类"
/>
/>
</el-
col
>
</el-
form-item
>
<el-
col
:span=
"6
"
>
<el-
form-item
label=
"创建时间"
prop=
"createTime
"
>
<el-date-picker
<el-date-picker
v-model=
"queryParams.createTime"
v-model=
"queryParams.createTime"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
...
@@ -32,8 +38,8 @@
...
@@ -32,8 +38,8 @@
type=
"daterange"
type=
"daterange"
value-format=
"YYYY-MM-DD HH:mm:ss"
value-format=
"YYYY-MM-DD HH:mm:ss"
/>
/>
</el-
col
>
</el-
form-item
>
<el-
col
:span=
"6"
>
<el-
form-item
>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
搜索
...
@@ -42,30 +48,32 @@
...
@@ -42,30 +48,32 @@
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
重置
</el-button>
</el-button>
</el-
col
>
</el-
form-item
>
</el-
row
>
</el-
form
>
<el-table
v-loading=
"loading"
:data=
"list"
show-overflow-tooltip
>
<el-table
v-loading=
"loading"
:data=
"list"
show-overflow-tooltip
>
<!--
多选模式
-->
<!--
1. 多选模式(不能使用type="selection",Element会忽略Header插槽)
-->
<el-table-column
key=
"2"
type=
"selection"
width=
"55"
v-if=
"multiple"
>
<el-table-column
width=
"55"
v-if=
"multiple"
>
<template
#
header
>
<template
#
header
>
<el-checkbox
<el-checkbox
:value=
"allChecked && checkedPageNos.indexOf(queryParams.pageNo) > -1"
v-model=
"isCheckAll"
:indeterminate=
"isIndeterminate"
@
change=
"handleCheckAll"
@
change=
"handleCheckAll"
/>
/>
</
template
>
</
template
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-checkbox
<el-checkbox
:value=
"checkedSpuIds.indexOf(row.id) > -1
"
v-model=
"checkedStatus[row.id]
"
@
change=
"(checked: boolean) => handleCheckOne(checked, row)"
@
change=
"(checked: boolean) => handleCheckOne(checked, row
, true
)"
/>
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<!-- 单选模式 -->
<!--
2.
单选模式 -->
<el-table-column
label=
"#"
width=
"55"
v-else
>
<el-table-column
label=
"#"
width=
"55"
v-else
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-radio
:label=
"row.id"
v-model=
"selectedSpuId"
@
change=
"handleSingleSelected(row)"
<el-radio
:label=
"row.id"
v-model=
"selectedSpuId"
@
change=
"handleSingleSelected(row)"
>
>
</el-radio
<!-- 空格不能省略,是为了让单选框不显示label,如果不指定label不会有选中的效果 -->
>
</el-radio>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号"
prop=
"id"
min-width=
"60"
/>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号"
prop=
"id"
min-width=
"60"
/>
...
@@ -102,54 +110,71 @@
...
@@ -102,54 +110,71 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
ElTable
}
from
'element-plus'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
CHANGE_EVENT
}
from
'element-plus'
type
Spu
=
Required
<
ProductSpuApi
.
Spu
>
type
Spu
=
Required
<
ProductSpuApi
.
Spu
>
/**
* 商品表格选择对话框
* 1. 单选模式:
* 1.1 点击表格左侧的单选框时,结束选择,并关闭对话框
* 1.2 再次打开时,保持选中状态
* 2. 多选模式:
* 2.1 点击表格左侧的多选框时,记录选中的商品
* 2.2 切换分页时,保持商品的选中的状态
* 2.3 点击右下角的确定按钮时,结束选择,关闭对话框
* 2.4 再次打开时,保持选中状态
*/
defineOptions
({
name
:
'SpuTableSelect'
})
defineOptions
({
name
:
'SpuTableSelect'
})
const
props
=
defineProps
({
defineProps
({
// 多选
// 多选
模式
multiple
:
propTypes
.
bool
.
def
(
false
)
multiple
:
propTypes
.
bool
.
def
(
false
)
})
})
const
total
=
ref
(
0
)
// 列表的总页数
// 列表的总页数
const
list
=
ref
<
Spu
[]
>
([])
// 列表的数据
const
total
=
ref
(
0
)
const
loading
=
ref
(
false
)
// 列表的加载中
// 列表的数据
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
list
=
ref
<
Spu
[]
>
([])
// 列表的加载中
const
loading
=
ref
(
false
)
// 弹窗的是否展示
const
dialogVisible
=
ref
(
false
)
// 查询参数
const
queryParams
=
ref
({
const
queryParams
=
ref
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
tabType
:
0
,
// 默认获取上架的商品
// 默认获取上架的商品
tabType
:
0
,
name
:
''
,
name
:
''
,
categoryId
:
null
,
categoryId
:
null
,
createTime
:
[]
createTime
:
[]
})
// 查询参数
})
const
selectedSpuId
=
ref
()
// 选中的商品 spuId
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
(
spus
?:
Spu
[])
=>
{
const
open
=
(
spuList
?:
Spu
[])
=>
{
if
(
spus
&&
spus
.
length
>
0
)
{
// 重置
// todo check-box不显示选中?
checkedSpus
.
value
=
[]
checkedSpus
.
value
=
[...
spus
]
checkedStatus
.
value
=
{}
checkedSpuIds
.
value
=
spus
.
map
((
spu
)
=>
spu
.
id
)
isCheckAll
.
value
=
false
}
else
{
isIndeterminate
.
value
=
false
checkedSpus
.
value
=
[]
checkedSpuIds
.
value
=
[]
// 处理已选中
if
(
spuList
&&
spuList
.
length
>
0
)
{
checkedSpus
.
value
=
[...
spuList
]
checkedStatus
.
value
=
Object
.
fromEntries
(
spuList
.
map
(
spu
=>
[
spu
.
id
,
true
]))
}
}
allChecked
.
value
=
false
checkedPageNos
.
value
=
[]
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
resetQuery
()
resetQuery
()
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
...
@@ -158,6 +183,10 @@ const getList = async () => {
...
@@ -158,6 +183,10 @@ const getList = async () => {
const
data
=
await
ProductSpuApi
.
getSpuPage
(
queryParams
.
value
)
const
data
=
await
ProductSpuApi
.
getSpuPage
(
queryParams
.
value
)
list
.
value
=
data
.
list
list
.
value
=
data
.
list
total
.
value
=
data
.
total
total
.
value
=
data
.
total
// checkbox绑定undefined会有问题,需要给一个bool值
list
.
value
.
forEach
(
spu
=>
checkedStatus
.
value
[
spu
.
id
]
=
checkedStatus
.
value
[
spu
.
id
]
||
false
)
// 计算全选框状态
calculateIsCheckAll
()
}
finally
{
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
}
...
@@ -174,7 +203,8 @@ const resetQuery = () => {
...
@@ -174,7 +203,8 @@ const resetQuery = () => {
queryParams
.
value
=
{
queryParams
.
value
=
{
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
tabType
:
0
,
// 默认获取上架的商品
// 默认获取上架的商品
tabType
:
0
,
name
:
''
,
name
:
''
,
categoryId
:
null
,
categoryId
:
null
,
createTime
:
[]
createTime
:
[]
...
@@ -182,65 +212,89 @@ const resetQuery = () => {
...
@@ -182,65 +212,89 @@ const resetQuery = () => {
getList
()
getList
()
}
}
const
allChecked
=
ref
(
false
)
//是否全选
// 是否全选
const
checkedPageNos
=
ref
<
number
[]
>
([])
//选中的页码
const
isCheckAll
=
ref
(
false
)
const
checkedSpuIds
=
ref
<
number
[]
>
([])
//选中的商品ID
// 全选框是否处于中间状态:不是全部选中 && 任意一个选中
const
checkedSpus
=
ref
<
Spu
[]
>
([])
//选中的商品
const
isIndeterminate
=
ref
(
false
)
// 选中的商品
const
checkedSpus
=
ref
<
Spu
[]
>
([])
// 选中状态:key为商品ID,value为是否选中
const
checkedStatus
=
ref
<
Record
<
string
,
boolean
>>
({})
// 选中的商品 spuId
const
selectedSpuId
=
ref
()
/** 单选中时触发 */
/** 单选中时触发 */
const
handleSingleSelected
=
(
row
:
Spu
)
=>
{
const
handleSingleSelected
=
(
spu
:
Spu
)
=>
{
emits
(
'change'
,
row
)
emits
(
CHANGE_EVENT
,
spu
)
// 关闭弹窗
// 关闭弹窗
dialogVisible
.
value
=
false
dialogVisible
.
value
=
false
// 记住上次选择的ID
// 记住上次选择的ID
selectedSpuId
.
value
=
row
.
id
selectedSpuId
.
value
=
spu
.
id
}
}
/** 多选完成 */
/** 多选完成 */
const
handleEmitChange
=
()
=>
{
const
handleEmitChange
=
()
=>
{
// 关闭弹窗
// 关闭弹窗
dialogVisible
.
value
=
false
dialogVisible
.
value
=
false
emits
(
'change'
,
[...
checkedSpus
.
value
])
emits
(
CHANGE_EVENT
,
[...
checkedSpus
.
value
])
}
}
/** 确认选择时的触发事件 */
/** 确认选择时的触发事件 */
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
(
e
:
'change'
,
spu
:
Spu
|
Spu
[]
|
any
):
void
change
:
[
spu
:
Spu
|
Spu
[]
|
any
]
}
>
()
}
>
()
/** 全选 */
/** 全选
/全不选
*/
const
handleCheckAll
=
(
checked
:
boolean
)
=>
{
const
handleCheckAll
=
(
checked
:
boolean
)
=>
{
debugger
isCheckAll
.
value
=
checked
console
.
log
(
'checkAll'
,
checked
)
isIndeterminate
.
value
=
false
allChecked
.
value
=
checked
const
index
=
checkedPageNos
.
value
.
indexOf
(
queryParams
.
value
.
pageNo
)
checkedPageNos
.
value
.
push
(
queryParams
.
value
.
pageNo
)
if
(
index
>
-
1
)
{
checkedPageNos
.
value
.
splice
(
index
,
1
)
}
list
.
value
.
forEach
((
item
)
=>
handleCheckOne
(
checked
,
item
))
list
.
value
.
forEach
((
spu
)
=>
handleCheckOne
(
checked
,
spu
,
false
))
}
}
/** 选中一行 */
/**
const
handleCheckOne
=
(
checked
:
boolean
,
spu
:
Spu
)
=>
{
* 选中一行
* @param checked 是否选中
* @param spu 商品
* @param isCalcCheckAll 是否计算全选
*/
const
handleCheckOne
=
(
checked
:
boolean
,
spu
:
Spu
,
isCalcCheckAll
:
boolean
)
=>
{
if
(
checked
)
{
if
(
checked
)
{
const
index
=
checkedSpuIds
.
value
.
indexOf
(
spu
.
id
)
checkedSpus
.
value
.
push
(
spu
)
if
(
index
===
-
1
)
{
checkedStatus
.
value
[
spu
.
id
]
=
true
checkedSpuIds
.
value
.
push
(
spu
.
id
)
checkedSpus
.
value
.
push
(
spu
)
}
}
else
{
}
else
{
const
index
=
checkedSpuIds
.
value
.
indexOf
(
spu
.
id
)
const
index
=
findCheckedIndex
(
spu
)
if
(
index
>
-
1
)
{
if
(
index
>
-
1
)
{
checkedSpuIds
.
value
.
splice
(
index
,
1
)
checkedSpus
.
value
.
splice
(
index
,
1
)
checkedSpus
.
value
.
splice
(
index
,
1
)
checkedStatus
.
value
[
spu
.
id
]
=
false
isCheckAll
.
value
=
false
}
}
}
}
// 计算全选框状态
if
(
isCalcCheckAll
){
calculateIsCheckAll
()
}
}
// 查找商品在已选中商品列表中的索引
const
findCheckedIndex
=
(
spu
:
Spu
)
=>
checkedSpus
.
value
.
findIndex
(
item
=>
item
.
id
===
spu
.
id
)
// 计算全选框状态
const
calculateIsCheckAll
=
()
=>
{
isCheckAll
.
value
=
list
.
value
.
every
(
spu
=>
{
let
valueElement
=
checkedStatus
.
value
[
spu
.
id
];
debugger
return
valueElement
;
});
// 计算中间状态:不是全部选中 && 任意一个选中
isIndeterminate
.
value
=
!
isCheckAll
.
value
&&
list
.
value
.
some
(
spu
=>
checkedStatus
.
value
[
spu
.
id
])
}
}
const
categoryList
=
ref
()
// 分类列表
// 分类列表
const
categoryTreeList
=
ref
()
// 分类树
const
categoryList
=
ref
()
// 分类树
const
categoryTreeList
=
ref
()
/** 初始化 **/
/** 初始化 **/
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
getList
()
await
getList
()
...
...
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