Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qr-consistency-vue3
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
刘怀志
qr-consistency-vue3
Commits
756474e0
Commit
756474e0
authored
Apr 24, 2025
by
yanzhengyang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增选择用户公共组件
parent
be4b2904
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
347 additions
and
5 deletions
+347
-5
index.vue
src/components/SelectRole/index.vue
+210
-0
view.vue
...olPlan/CCAPControlPlan/CCAPControlPlanManagement/view.vue
+137
-5
No files found.
src/components/SelectRole/index.vue
0 → 100644
View file @
756474e0
<
template
>
<el-dialog
v-model=
"selectRole"
title=
"选择用户"
style=
"width: 720px;font-weight: 800"
@
close=
"closeDialog"
>
<div
class=
"dialog-box"
>
<div
class=
"dialog-box-left"
>
<el-form
:inline=
"true"
class=
"demo-form-inline"
:model=
"allRole"
style=
"width: 100%;padding-top: 15px;background-color: #f4f4f9"
>
<el-form-item>
<el-input
v-model=
"allRole"
placeholder=
"请输入机构或成员名称"
clearable
style=
"width: 180px;margin-left: 20px"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
icon=
"Search"
@
click=
"selectSearch"
circle
></el-button>
</el-form-item>
</el-form>
<div
class=
"demo-collapse"
>
<el-collapse
v-model=
"activeNames"
>
<el-collapse-item
:title=
"item[deptKey]"
:name=
"item.id"
v-for=
"(item, index) in filteredDeptList"
:key=
"index"
style=
"margin-left: 20px"
>
<div
v-for=
"it in (Array.isArray(item[nameKey]) ? item[nameKey] : [item[nameKey]])"
:key=
"it[nameKey]"
>
<el-checkbox
v-model=
"checked1"
:label=
"it[nameKey]"
:disabled=
"props.selectionMode === 'single' && checked1.length >= 1"
size=
"large"
/>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
<div
class=
"dialog-box-right"
>
<div
class=
"box-right-header"
>
<P
v-if=
"props.selectionMode === 'single'"
>
单选
</P>
<p
v-if=
"props.selectionMode === 'multiple'"
>
已选
{{
selectedItems
.
length
}}
/
{{
totalItems
}}
</p>
<el-button
icon=
"Delete"
@
click=
"clearAllSelected"
>
清空
</el-button>
</div>
<div
class=
"box-right-content"
>
<div
class=
"content-item"
v-for=
"(item, index) in selectedItems"
:key=
"index"
>
<span
style=
"font-size: 14px;font-weight: 400"
>
{{
item
}}
</span>
<el-button
icon=
"Delete"
@
click=
"removeItem(index)"
type=
"primary"
circle
></el-button>
</div>
</div>
</div>
</div>
<div
style=
"margin-top: 20px;margin-left: 78%"
>
<el-button
@
click=
"closeDialog"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitSelection"
>
确定
</el-button>
</div>
</el-dialog>
</
template
>
<
script
setup
>
import
{
ref
,
watch
}
from
'vue'
;
import
{
defineProps
,
defineEmits
}
from
'vue'
;
// 接收父组件传入的props
const
props
=
defineProps
({
flag
:
{
type
:
Boolean
,
default
:
false
},
deptList
:
{
type
:
Array
,
required
:
true
},
nameKey
:
{
// 成员名称字段名(默认'name')
type
:
String
,
default
:
'name'
},
deptKey
:
{
// 部门名称字段名(默认'dept')
type
:
String
,
default
:
'dept'
},
selectionMode
:
{
// 单选/多选模式参数
type
:
String
,
default
:
'multiple'
,
// 'single' | 'multiple'
validator
:
(
v
)
=>
[
'single'
,
'multiple'
].
includes
(
v
)
}
});
// 事件传递到父组件
const
emit
=
defineEmits
([
'close'
,
'submit'
]);
// 声明组件的状态
const
selectRole
=
ref
(
props
.
flag
);
const
allRole
=
ref
(
''
);
const
checked1
=
ref
([]);
const
selectedItems
=
ref
([]);
const
filteredDeptList
=
ref
(
props
.
deptList
);
const
activeNames
=
ref
([
props
.
deptList
[
0
].
id
]);
// 新增展开项绑定
// 计算左侧总项数:遍历deptList并计算所有成员数量
const
totalItems
=
computed
(()
=>
{
return
props
.
deptList
.
reduce
((
total
,
dept
)
=>
total
+
dept
.
name
.
length
,
0
);
});
// 搜索功能:根据输入内容过滤部门列表
const
selectSearch
=
()
=>
{
if
(
!
allRole
.
value
)
{
filteredDeptList
.
value
=
props
.
deptList
;
// 如果搜索框为空,恢复所有项
activeNames
.
value
=
[
props
.
deptList
[
0
].
id
];
checked1
.
value
=
[];
// 清空展开项
}
else
{
const
searchTerm
=
allRole
.
value
.
toLowerCase
();
const
matchedNames
=
[];
filteredDeptList
.
value
=
props
.
deptList
.
filter
(
item
=>
{
const
deptMatch
=
item
[
props
.
deptKey
].
toLowerCase
().
includes
(
searchTerm
);
const
nameMatch
=
item
[
props
.
nameKey
].
some
(
it
=>
{
const
name
=
it
[
props
.
nameKey
]
?
it
[
props
.
nameKey
]
:
it
;
const
isMatch
=
name
.
toLowerCase
().
includes
(
searchTerm
);
if
(
isMatch
)
matchedNames
.
push
(
name
);
// 收集匹配的成员名称
return
isMatch
;
});
return
deptMatch
||
nameMatch
;
});
// 自动添加匹配的成员到选中列表(去重)
checked1
.
value
=
[...
new
Set
([...
checked1
.
value
,
...
matchedNames
])];
activeNames
.
value
=
filteredDeptList
.
value
.
map
(
item
=>
item
.
id
);
}
};
// watch监听props更新,保持同步
watch
(()
=>
props
.
flag
,
(
newVal
)
=>
{
selectRole
.
value
=
newVal
;
});
watch
(
checked1
,
(
newVal
)
=>
{
if
(
props
.
selectionMode
===
'single'
)
{
selectedItems
.
value
=
newVal
.
slice
(
-
1
);
// 单选模式只保留最后一个
}
else
{
selectedItems
.
value
=
[...
newVal
];
}
});
// 清空已选项
const
clearAllSelected
=
()
=>
{
selectedItems
.
value
=
[];
checked1
.
value
=
[];
};
// 删除单个已选项
const
removeItem
=
(
index
)
=>
{
const
removedItem
=
selectedItems
.
value
[
index
];
// 先获取要删除的项
selectedItems
.
value
.
splice
(
index
,
1
);
checked1
.
value
=
checked1
.
value
.
filter
(
item
=>
item
!==
removedItem
);
};
// 关闭对话框
const
closeDialog
=
()
=>
{
emit
(
'close'
)
// 更新父组件v-model
clearAllSelected
();
// 清空已选项
allRole
.
value
=
''
;
// 清空搜索框
filteredDeptList
.
value
=
props
.
deptList
;
activeNames
.
value
=
[
props
.
deptList
[
0
].
id
]
// 重置展开项绑定
};
// 提交选择
const
submitSelection
=
()
=>
{
if
(
selectedItems
.
value
.
length
>
0
)
{
emit
(
'submit'
,
selectedItems
.
value
);
// 仅在选中项存在时向父组件提交
}
closeDialog
();
// 关闭弹框
};
</
script
>
<
style
scoped
>
.dialog-box
{
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
.dialog-box-left{
border
:
1px
solid
#f4f4f9
;
width
:
320px
;
height
:
500px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.demo-collapse{
width
:
100%
;
background-color
:
white
;
overflow
:
auto
;
}
}
.dialog-box-right
{
border
:
1px
solid
#f4f4f9
;
width
:
320px
;
height
:
500px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.box-right-header{
width
:
100%
;
height
:
65px
;
background-color
:
#f4f4f9
;
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
font-size
:
16px
;
}
.box-right-content
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
width
:
100%
;
.content-item{
width
:
100%
;
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
margin-top
:
10px
;
}
}
}
}
</
style
>
src/views/controlPlan/CCAPControlPlan/CCAPControlPlanManagement/view.vue
View file @
756474e0
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
<div>
<div>
<div
class=
"tab-components"
>
<div
class=
"tab-components"
>
<span
class=
"components-span"
>
编制详情
</span>
<span
class=
"components-span"
>
编制详情
</span>
<el-button
class=
"btn-A"
>
查看变更履历
</el-button>
<el-button
class=
"btn-A"
@
click=
"changeView"
>
查看变更履历
</el-button>
</div>
</div>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
...
@@ -133,6 +133,8 @@
...
@@ -133,6 +133,8 @@
<el-form-item>
<el-form-item>
<el-button
class=
"btn-A"
icon=
"Search"
@
click=
"handleQuery"
>
搜索
</el-button>
<el-button
class=
"btn-A"
icon=
"Search"
@
click=
"handleQuery"
>
搜索
</el-button>
<el-button
class=
"btn-B"
icon=
"Refresh"
@
click=
"resetQuery"
>
重置
</el-button>
<el-button
class=
"btn-B"
icon=
"Refresh"
@
click=
"resetQuery"
>
重置
</el-button>
<el-button
class=
"btn-A"
@
click=
"singleOpenDialog"
>
选择用户(单选)
</el-button>
<el-button
class=
"btn-A"
@
click=
"openDialog"
>
选择用户(多选)
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
<el-table
:data=
"tableData"
style=
"width: 100%"
border
>
<el-table
:data=
"tableData"
style=
"width: 100%"
border
>
...
@@ -163,7 +165,7 @@
...
@@ -163,7 +165,7 @@
<div>
<div>
<div
class=
"tab-components"
>
<div
class=
"tab-components"
>
<span
class=
"components-span"
>
编制详情
</span>
<span
class=
"components-span"
>
编制详情
</span>
<el-button
class=
"btn-A"
>
查看变更履历
</el-button>
<el-button
class=
"btn-A"
@
click=
"changeView"
>
查看变更履历
</el-button>
</div>
</div>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
...
@@ -255,7 +257,7 @@
...
@@ -255,7 +257,7 @@
<div>
<div>
<div
class=
"tab-components"
>
<div
class=
"tab-components"
>
<span
class=
"components-span"
>
编制详情
</span>
<span
class=
"components-span"
>
编制详情
</span>
<el-button
class=
"btn-A"
>
查看变更履历
</el-button>
<el-button
class=
"btn-A"
@
click=
"changeView"
>
查看变更履历
</el-button>
</div>
</div>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
...
@@ -365,7 +367,7 @@
...
@@ -365,7 +367,7 @@
<div>
<div>
<div
class=
"tab-components"
>
<div
class=
"tab-components"
>
<span
class=
"components-span"
>
编制详情
</span>
<span
class=
"components-span"
>
编制详情
</span>
<el-button
class=
"btn-A"
>
查看变更履历
</el-button>
<el-button
class=
"btn-A"
@
click=
"changeView"
>
查看变更履历
</el-button>
</div>
</div>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions
border
:column=
"4"
style=
"margin-top: 20px"
>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
<el-descriptions-item
label=
"文件编号:"
label-align=
"right"
>
kooriookami
</el-descriptions-item>
...
@@ -459,14 +461,33 @@
...
@@ -459,14 +461,33 @@
</el-tabs>
</el-tabs>
</div>
</div>
</div>
</div>
<!-- 测试 -->
<select-role
v-model=
"selectRole"
:dept-list=
"deptList"
name-key=
"name"
dept-key=
"dept"
:selection-mode=
"selectType"
@
submit=
"handleSelectionSubmit"
@
close=
"() => selectRole = false"
/>
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
useRoute
}
from
"vue-router"
;
import
SelectRole
from
"@/components/SelectRole/index.vue"
const
{
proxy
}
=
getCurrentInstance
();
const
{
proxy
}
=
getCurrentInstance
();
import
{
ref
,
getCurrentInstance
}
from
'vue'
import
{
ref
,
getCurrentInstance
}
from
'vue'
const
route
=
useRoute
()
const
total
=
ref
(
0
)
const
total
=
ref
(
0
)
const
formList
=
ref
([])
const
formList
=
ref
([])
const
activeTab
=
ref
(
'first'
)
// 默认激活第一个标签页
const
activeTab
=
ref
(
'first'
)
// 默认激活第一个标签页
if
(
route
.
query
.
tab
){
activeTab
.
value
=
route
.
query
.
tab
}
const
radio1
=
ref
(
'1'
)
const
radio1
=
ref
(
'1'
)
const
templateDetailList
=
ref
([])
const
templateDetailList
=
ref
([])
// 修改data定义方式
// 修改data定义方式
...
@@ -474,7 +495,68 @@ const queryParams = ref({
...
@@ -474,7 +495,68 @@ const queryParams = ref({
pageNum
:
1
,
pageNum
:
1
,
pageSize
:
10
pageSize
:
10
})
})
const
selectRole
=
ref
(
false
)
const
selectType
=
ref
(
''
)
//多选
const
openDialog
=
()
=>
{
selectRole
.
value
=
true
;
// 打开对话框
selectType
.
value
=
'multiple'
;
};
//单选
const
singleOpenDialog
=
()
=>
{
selectRole
.
value
=
true
;
// 打开对话框
selectType
.
value
=
'single'
};
const
handleSelectionSubmit
=
(
selectedItems
)
=>
{
console
.
log
(
'已选中的项:'
,
selectedItems
);
// 处理已选择的用户
};
const
deptList
=
[
{
id
:
1
,
dept
:
'前端'
,
name
:
[
{
name
:
'北京'
},
{
name
:
'上海'
},
{
name
:
'天津'
},
{
name
:
'重庆'
},
],
address
:
'No. 189, Grove St, Los Angeles'
,
},
{
id
:
2
,
dept
:
'后端'
,
name
:
[
{
name
:
'杭州'
},
{
name
:
'西安'
},
{
name
:
'深圳'
},
{
name
:
'青岛'
},
],
address
:
'No. 189, Grove St, Los Angeles'
,
},
{
id
:
3
,
dept
:
'测试'
,
name
:
[
{
name
:
'北京'
},
{
name
:
'上海'
},
{
name
:
'天津'
},
{
name
:
'重庆'
},
],
address
:
'No. 189, Grove St, Los Angeles'
,
},
{
id
:
4
,
dept
:
'运维'
,
name
:
[
{
name
:
'北京'
},
{
name
:
'上海'
},
{
name
:
'天津'
},
{
name
:
'重庆'
},
],
address
:
'No. 189, Grove St, Los Angeles'
,
},
]
watch
(
activeTab
,
(
newVal
)
=>
{
watch
(
activeTab
,
(
newVal
)
=>
{
queryParams
.
value
.
pageNum
=
1
// 切换标签时重置页码
queryParams
.
value
.
pageNum
=
1
// 切换标签时重置页码
...
@@ -506,7 +588,10 @@ const handlePagination = ({ page, limit }) => {
...
@@ -506,7 +588,10 @@ const handlePagination = ({ page, limit }) => {
// })
// })
// }
// }
const
handleBack
=
()
=>
{
const
handleBack
=
()
=>
{
proxy
.
$router
.
push
({
path
:
'/control/CCAPControlPlan/CCAPControlPlanManagementIndex'
});
proxy
.
$router
.
push
({
path
:
'/control/CCAPControlPlan/index'
});
}
const
changeView
=
()
=>
{
proxy
.
$router
.
push
({
path
:
'/control/CCAPControlPlan/change'
,
query
:
{
tab
:
activeTab
.
value
}})
}
}
onMounted
(()
=>
{
onMounted
(()
=>
{
// getFrom();
// getFrom();
...
@@ -533,4 +618,51 @@ onMounted(() => {
...
@@ -533,4 +618,51 @@ onMounted(() => {
}
}
}
}
}
}
.dialog-box
{
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
.dialog-box-left
{
border
:
1px
solid
#f4f4f9
;
width
:
320px
;
height
:
500px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.demo-collapse
{
width
:
100%
;
background-color
:
white
;
}
}
.dialog-box-right
{
border
:
1px
solid
#f4f4f9
;
width
:
320px
;
height
:
500px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.box-right-header
{
width
:
100%
;
height
:
65px
;
background-color
:
#f4f4f9
;
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
font-size
:
18px
;
}
.box-right-content
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
width
:
100%
;
.content-item
{
width
:
100%
;
display
:
flex
;
justify-content
:
space-around
;
align-items
:
center
;
margin-top
:
10px
;
}
}
}
}
</
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