Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
psa-web
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
高滢
psa-web
Commits
ce416485
Commit
ce416485
authored
Mar 20, 2025
by
wangjiancheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:新增项目下拉框
parent
ed88a5b4
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
82 additions
and
124 deletions
+82
-124
project.js
src/api/project/project.js
+8
-0
add.vue
src/views/project/add.vue
+21
-36
draft.vue
src/views/project/draft.vue
+2
-24
edit.vue
src/views/project/edit.vue
+25
-40
index.vue
src/views/project/index.vue
+14
-19
view.vue
src/views/project/view.vue
+12
-5
No files found.
src/api/project/project.js
View file @
ce416485
...
...
@@ -68,3 +68,11 @@ export function logicRemove(id) {
method
:
'delete'
})
}
// 获取项目 (下拉框)
export
function
getProjectList
()
{
return
request
({
url
:
'/system/project/getProjectList'
,
method
:
'get'
})
}
src/views/project/add.vue
View file @
ce416485
...
...
@@ -108,7 +108,7 @@
type=
"textarea"
v-model=
"form.projectDescribe"
placeholder=
"请输入项目描述"
:autosize=
"
{ minRows: 5, maxRows:
1
0 }"
:autosize=
"
{ minRows: 5, maxRows:
2
0 }"
style="width: 97%"
>
</el-input>
</el-form-item>
...
...
@@ -119,8 +119,6 @@
action=
"https://jsonplaceholder.typicode.com/posts/"
:on-preview=
"handlePreview"
:on-remove=
"handleRemove"
:before-remove=
"beforeRemove"
:file-list=
"form.projectAnnexList"
:on-exceed=
"handleExceed"
:auto-upload=
"false"
:on-success=
"handleSuccess"
...
...
@@ -131,8 +129,6 @@
</el-button>
</el-upload>
</el-form-item>
<!--
</el-col>
<el-col
:span=
"10"
>
-->
<el-form-item
label=
"项目回款笔数"
prop=
"repaymentDetails"
>
<el-select
v-model=
"form.repaymentCount"
...
...
@@ -157,6 +153,7 @@
<el-input
v-model=
"item.repaymentPercentage"
placeholder=
"请输入回款百分比"
maxlength=
"10"
@
blur=
"checkPercentage(item.repaymentPercentage, index)"
style=
"width: 97%"
>
...
...
@@ -227,7 +224,20 @@ const rules = ref({
{
required
:
true
,
message
:
'预计开始时间不能为空'
,
trigger
:
'blur'
}
],
endDate
:
[
{
required
:
true
,
message
:
'预计结束时间不能为空'
,
trigger
:
'blur'
}
{
required
:
true
,
message
:
'预计结束时间不能为空'
,
trigger
:
'blur'
},
// 预计结束时间必须大于预计开始时间
{
validator
:
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
callback
(
new
Error
(
'请选择预计结束时间'
));
}
else
if
(
value
<=
form
.
startDate
)
{
callback
(
new
Error
(
'预计结束时间必须大于预计开始时间'
));
}
else
{
callback
();
}
},
trigger
:
'blur'
}
],
departmentLeadId
:
[
{
required
:
true
,
message
:
'部门负责人不能为空'
,
trigger
:
'blur'
}
...
...
@@ -236,7 +246,7 @@ const rules = ref({
{
required
:
true
,
message
:
'项目经理不能为空'
,
trigger
:
'blur'
}
],
projectCost
:
[
{
required
:
true
,
message
:
'项目成本不能为空'
,
trigger
:
'blur'
}
{
required
:
true
,
message
:
'项目成本不能为空'
,
trigger
:
'blur'
}
,
],
projectStatus
:
[
{
required
:
true
,
message
:
'项目状态不能为空'
,
trigger
:
'blur'
}
...
...
@@ -257,16 +267,8 @@ const getUserList = () => {
}
})
})
/* selectUserListByRoleId(104).then(response => {
headOptions.value = response.data.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
})
selectUserListByRoleId(100).then(response => {
// 获取项目经理
/* selectUserListByRoleId(100).then(response => {
managerOptions.value = response.data.map(item => {
return {
value: item.userId,
...
...
@@ -386,10 +388,8 @@ const beforeRemove = (file, fileList) => {
const
handleSuccess
=
(
response
,
file
,
fileList
)
=>
{
console
.
log
(
response
,
file
,
fileList
)
}
// 在组件挂载时执行
onMounted
(()
=>
{
getUserList
()
});
getUserList
()
</
script
>
<
style
scoped
lang=
"scss"
>
...
...
@@ -403,19 +403,4 @@ onMounted(() => {
letter-spacing
:
0
;
line-height
:
15px
;
}
.member-select
{
display
:
inline-block
;
margin-right
:
8px
;
/* 设置下拉框之间的间距为8px */
margin-bottom
:
8px
;
/* 设置下拉框之间的垂直间距为8px */
}
.el-button--text
{
margin-left
:
8px
;
/* 设置按钮与最后一个下拉框之间的间距为8px */
}
.inputS
{
width
:
400px
;
height
:
40px
;
border-radius
:
2px
;
}
</
style
>
src/views/project/draft.vue
View file @
ce416485
...
...
@@ -163,7 +163,7 @@
{{
scope
.
row
.
repaymentPercentage
}}
%
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"回款前置条件"
align
=
"center"
prop
=
"repaymentCondition"
>
<
el
-
table
-
column
label
=
"回款前置条件"
align
=
"center"
prop
=
"repaymentCondition"
show
-
overflow
-
tooltip
>
<
template
#
default
=
"scope"
>
{{
scope
.
row
.
repaymentCondition
||
'-'
}}
<
/template
>
...
...
@@ -211,11 +211,8 @@ const { proxy } = getCurrentInstance();
const
{
project_status
,
project_type
}
=
proxy
.
useDict
(
'project_status'
,
'project_type'
);
const
projectList
=
ref
([]);
const
open
=
ref
(
false
);
const
loading
=
ref
(
true
);
const
showSearch
=
ref
(
true
);
const
ids
=
ref
([]);
const
multiple
=
ref
(
true
);
const
total
=
ref
(
0
);
// 定义是否展开的状态
const
isExpanded
=
ref
(
false
);
...
...
@@ -287,7 +284,7 @@ const toggleSearch = () => {
/** 逻辑删除按钮操作 */
function
handleDelete
(
row
)
{
const
_ids
=
row
.
id
||
ids
.
value
;
const
_ids
=
row
.
id
;
proxy
.
$modal
.
confirm
(
'是否确认删除项目为"'
+
row
.
projectName
+
'"的数据项?'
).
then
(
function
()
{
return
logicRemove
(
_ids
);
}
).
then
(()
=>
{
...
...
@@ -314,26 +311,7 @@ getList();
letter
-
spacing
:
0
;
line
-
height
:
15
px
;
}
.
searchT
{
background
:
#
FFFFFF
;
box
-
shadow
:
0
2
px
2
px
0
#
b3b3b380
;
border
-
radius
:
2
px
;
padding
-
top
:
20
px
;
display
:
flex
;
justify
-
content
:
center
;
/* 水平居中 */
align
-
items
:
center
;
/* 垂直居中 */
}
.
searchB
{
margin
-
top
:
16
px
;
height
:
calc
(
100
vh
-
234
px
);
overflow
:
hidden
;
background
:
#
FFFFFF
;
box
-
shadow
:
0
2
px
2
px
0
#
b3b3b380
;
border
-
radius
:
2
px
;
}
.
pagination
-
containerA
{
//display: flex;
//justify-content: center; /* 水平居中 */
padding
-
right
:
43
%
;
}
<
/style
>
src/views/project/edit.vue
View file @
ce416485
...
...
@@ -22,6 +22,7 @@
v-model=
"form.projectName"
placeholder=
"请输入项目名称"
size=
"large"
maxlength=
"50"
style=
"width: 97%"
/>
</el-form-item>
...
...
@@ -29,6 +30,7 @@
<el-select
v-model=
"form.projectType"
placeholder=
"请选择项目类型"
filterable
style=
"width: 97%"
size=
"large"
>
...
...
@@ -60,7 +62,7 @@
size=
"large"
/>
</el-form-item>
<el-form-item
label=
"事业部
门
负责人"
prop=
"departmentLeaderName"
>
<el-form-item
label=
"事业部负责人"
prop=
"departmentLeaderName"
>
<el-input
v-model=
"form.departmentLeaderName"
placeholder=
"请输入事业部门负责人"
...
...
@@ -74,6 +76,7 @@
v-model=
"form.projectManagerId"
placeholder=
"请选择项目经理"
style=
"width: 97%"
filterable
size=
"large"
>
<el-option
...
...
@@ -88,6 +91,7 @@
<el-input
v-model=
"form.projectCost"
placeholder=
"请输入项目成本"
type=
"number"
size=
"large"
style=
"width: 97%"
/>
...
...
@@ -105,23 +109,6 @@
:value=
"dict.value"
/>
</el-select>
</el-form-item>
<!--
<el-form-item
label=
"项目成员"
>
<el-select
v-model=
"form.projectMemberIds"
placeholder=
"请选择项目成员"
size=
"large"
multiple
filterable
style=
"width: 97%"
>
<el-option
v-for=
"dict in membersOptions"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
/>
</el-select>
</el-form-item>
-->
<el-form-item
label=
"项目成员"
prop=
"projectMemberIds"
>
<div
v-for=
"(member, index) in form.projectMemberIds"
:key=
"index"
class=
"member-select"
>
<el-select
...
...
@@ -132,7 +119,7 @@
clearable
filterable
@
change=
"onMemberChange(index,$event)"
v-hasPermi=
"['
project-manag
er']"
v-hasPermi=
"['
system:project:memb
er']"
>
<el-option
v-for=
"dict in filteredMembersOptions(index)"
...
...
@@ -148,7 +135,7 @@
v-model=
"form.projectDescribe"
type=
"textarea"
placeholder=
"请输入项目描述"
:autosize=
"
{ minRows: 5, maxRows:
7
}"
:autosize=
"
{ minRows: 5, maxRows:
20
}"
size="large"
style="width: 97%"
/>
...
...
@@ -157,30 +144,26 @@
<el-upload
list-type=
"text"
v-model:file-list=
"form.projectAnnexList"
class=
"upload-demo"
action=
"https://jsonplaceholder.typicode.com/posts/"
:on-preview=
"handlePreview"
:on-remove=
"handleRemove"
:before-remove=
"beforeRemove"
:file-list=
"form.projectAnnexList"
:on-change=
"handleChange"
:on-exceed=
"handleExceed"
:auto-upload=
"false"
:on-success=
"handleSuccess"
>
<el-button
size=
"large"
type=
"text"
>
<img
src=
"../../assets/icons/common/upl.png"
height=
"16"
width=
"16"
style=
"margin-right: 10px"
/>
<img
src=
"../../assets/icons/common/upl.png"
height=
"16"
width=
"16"
style=
"margin-right: 10px"
/>
点击上传附件
</el-button>
</el-upload>
</el-form-item>
<!--
</el-col>
<el-col
:span=
"10"
>
-->
<el-form-item
label=
"项目回款笔数"
prop=
"repaymentDetails"
>
<el-select
v-model=
"form.repaymentCount"
placeholder=
"请选择项目回款笔数"
@
change=
"updateRepaymentInputs"
size=
"large"
clearable
style=
"width: 97%"
>
<el-option
...
...
@@ -198,6 +181,7 @@
<el-input
v-model=
"item.repaymentPercentage"
placeholder=
"请输入回款百分比"
maxlength=
"10"
style=
"width: 97%"
>
<template
#
suffix
>
...
...
@@ -251,6 +235,7 @@ const form = ref({
departmentLeaderId
:
''
,
departmentLeaderName
:
''
,
projectManagerId
:
''
,
projectManagerName
:
''
,
projectMemberIds
:
[],
projectCost
:
''
,
projectDescribe
:
''
,
...
...
@@ -387,18 +372,27 @@ const submitForm = () => {
}
})
}
// 上传文件
const
handleChange
=
(
file
,
fileList
)
=>
{
console
.
log
(
file
,
fileList
)
}
// 当用户删除上传文件 比如从服务器删除文件(如果需要),更新本地文件列表等
const
handleRemove
=
(
file
,
fileList
)
=>
{
console
.
log
(
file
,
fileList
)
}
// 上传成功
const
handleSuccess
=
(
response
,
file
,
fileList
)
=>
{
console
.
log
(
response
,
file
,
fileList
)
}
// 上传后预览
const
handlePreview
=
(
file
)
=>
{
console
.
log
(
file
)
}
// 文件超出限制
const
handleExceed
=
(
files
,
fileList
)
=>
{
proxy
.
$message
.
warning
(
`当前限制选择 3 个文件,本次选择了
${
files
.
length
}
个文件,共选择了
${
files
.
length
+
fileList
.
length
}
个文件`
)
}
...
...
@@ -408,10 +402,9 @@ const cancel = () => {
proxy
.
$router
.
push
({
path
:
'/project'
})
resetForm
()
}
onMounted
(()
=>
{
getProjectManage
()
getUserList
()
})
getProjectManage
()
getUserList
()
</
script
>
<
style
scoped
lang=
"scss"
>
...
...
@@ -427,16 +420,8 @@ onMounted(() => {
}
.member-select
{
display
:
inline-block
;
margin-right
:
8px
;
/* 设置下拉框之间的间距为8px */
margin-bottom
:
8px
;
/* 设置下拉框之间的垂直间距为8px */
margin-right
:
8px
;
margin-bottom
:
8px
;
}
.el-button--text
{
margin-left
:
8px
;
/* 设置按钮与最后一个下拉框之间的间距为8px */
}
.inputS
{
width
:
400px
;
height
:
40px
;
border-radius
:
2px
;
}
</
style
>
src/views/project/index.vue
View file @
ce416485
...
...
@@ -131,7 +131,7 @@
<div
class=
"contentTable"
>
<div
style=
"padding-left: 8px ;margin-bottom: 20px"
>
<span
class=
"bold-text"
style=
"border-bottom: 3px solid #0062FF;"
>
项目列表
</span>
<span
style=
"padding-left:
80%
"
>
<span
style=
"padding-left:
1250px;
"
>
<el-button
class=
"el-button-primary-pain"
plain
...
...
@@ -159,41 +159,40 @@
</el-tooltip>
</span>
</div>
<div>
<el-alert
v-if=
"emptyMemberCount > 0 "
type=
"warning"
show-icon
v-hasPermi=
"['
project-manager
']"
v-hasPermi=
"['
system:project:alert
']"
>
<
template
#
default
>
<span>
{{
`您有 ${emptyMemberCount
}
个项目需添加成员`
}}
<
/span
>
<
a
style
=
"margin-left: 50px"
href
=
"#"
@
click
.
prevent
=
"goToAddMembers"
>
去添加
<
/a
>
<
/template
>
<
/el-alert
>
<
/div
>
<
el
-
table
v
-
loading
=
"loading"
:
data
=
"sortedProjectList"
border
style
=
"width: 100%"
:
row
-
class
-
name
=
"tableRowClassName"
>
<
el
-
table
-
column
type
=
"selection"
width
=
"56"
align
=
"center"
/>
<
el
-
table
-
column
label
=
"项目编号"
align
=
"center"
prop
=
"projectNumber"
min
-
width
=
"150"
/>
<
el
-
table
-
column
label
=
"项目名称"
align
=
"center"
prop
=
"projectName"
min
-
width
=
"120"
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"项目类型"
align
=
"center"
prop
=
"projectType"
min
-
width
=
"12
0
"
sortable
>
<
el
-
table
-
column
label
=
"项目类型"
align
=
"center"
prop
=
"projectType"
min
-
width
=
"12
5
"
sortable
>
<
template
#
default
=
"scope"
>
<
dict
-
tag
:
options
=
"project_type"
:
value
=
"scope.row.projectType"
/>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"预计开始时间"
align
=
"center"
prop
=
"startDate"
min
-
width
=
"13
0
"
>
<
el
-
table
-
column
label
=
"预计开始时间"
align
=
"center"
prop
=
"startDate"
min
-
width
=
"13
5
"
>
<
template
#
default
=
"scope"
>
<
span
>
{{
parseTime
(
scope
.
row
.
startDate
,
'{y
}
/{m
}
/{d
}
'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"预计结束时间"
align
=
"center"
prop
=
"endDate"
min
-
width
=
"13
0
"
>
<
el
-
table
-
column
label
=
"预计结束时间"
align
=
"center"
prop
=
"endDate"
min
-
width
=
"13
5
"
>
<
template
#
default
=
"scope"
>
<
span
>
{{
parseTime
(
scope
.
row
.
endDate
,
'{y
}
/{m
}
/{d
}
'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"事业部负责人"
align
=
"center"
prop
=
"departmentLeaderName"
min
-
width
=
"1
50
"
sortable
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"事业部负责人"
align
=
"center"
prop
=
"departmentLeaderName"
min
-
width
=
"1
65
"
sortable
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"项目经理"
align
=
"center"
prop
=
"projectManagerName"
min
-
width
=
"120"
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"项目成本(元)"
align
=
"center"
prop
=
"projectCost"
min
-
width
=
"1
2
0"
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"项目成本(元)"
align
=
"center"
prop
=
"projectCost"
min
-
width
=
"1
3
0"
show
-
overflow
-
tooltip
/>
<
el
-
table
-
column
label
=
"项目状态"
align
=
"center"
prop
=
"projectStatus"
min
-
width
=
"120"
>
<
template
#
default
=
"scope"
>
<
dict
-
tag
:
options
=
"project_status"
:
value
=
"scope.row.projectStatus"
/>
...
...
@@ -213,12 +212,12 @@
第
{{
scope
.
$index
+
1
}}
笔
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"回款百分比"
align
=
"center"
prop
=
"repaymentPercentage"
>
<
el
-
table
-
column
label
=
"回款百分比"
align
=
"center"
prop
=
"repaymentPercentage"
width
=
"120"
>
<
template
#
default
=
"scope"
>
{{
scope
.
row
.
repaymentPercentage
||
'-'
}}
%
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"回款前置条件"
align
=
"center"
prop
=
"repaymentCondition"
show
-
overflow
-
tooltip
>
<
el
-
table
-
column
label
=
"回款前置条件"
align
=
"center"
prop
=
"repaymentCondition"
show
-
overflow
-
tooltip
width
=
"150"
>
<
template
#
default
=
"scope"
>
{{
scope
.
row
.
repaymentCondition
||
'-'
}}
<
/template
>
...
...
@@ -271,7 +270,7 @@
<
/template
>
<
script
setup
name
=
"Project"
>
import
{
listProject
,
logicRemove
}
from
"../../api/project/project.js"
;
import
{
listProject
,
logicRemove
,
getProjectList
}
from
"../../api/project/project.js"
;
import
{
listUser
}
from
"../../api/system/user.js"
;
const
{
proxy
}
=
getCurrentInstance
();
const
{
project_status
,
project_type
}
=
proxy
.
useDict
(
'project_status'
,
'project_type'
);
...
...
@@ -280,7 +279,6 @@ const projectList = ref([]);
const
queryRef
=
ref
();
const
loading
=
ref
(
true
);
const
showSearch
=
ref
(
true
);
const
multiple
=
ref
(
true
);
const
total
=
ref
(
0
);
// 定义是否展开的状态
const
isExpanded
=
ref
(
false
);
...
...
@@ -331,8 +329,8 @@ const getUserList = () => {
}
}
)
}
)
listProjec
t
().
then
(
response
=>
{
projectOptions
.
value
=
response
.
rows
.
map
(
item
=>
{
getProjectLis
t
().
then
(
response
=>
{
projectOptions
.
value
=
response
.
data
.
map
(
item
=>
{
return
{
value
:
item
.
id
,
label
:
item
.
projectName
...
...
@@ -418,7 +416,7 @@ function handleDelete(row) {
function
handleExport
()
{
proxy
.
download
(
'system/project/export'
,
{
...
queryParams
.
value
}
,
`
project_${new Date().getTime()
}
.xlsx`
)
}
,
`
项目管理
.xlsx`
)
}
getList
();
...
...
@@ -438,7 +436,6 @@ getUserList()
// 表格的标头
:
deep
(.
el
-
table
th
.
el
-
table__cell
)
{
line
-
height
:
35
px
;
//height: 56px;
background
:
#
F6F8FC
!
important
;
}
...
...
@@ -448,8 +445,6 @@ getUserList()
}
.
pagination
-
containerA
{
//display: flex;
//justify-content: center; /* 水平居中 */
padding
-
right
:
43
%
;
}
...
...
src/views/project/view.vue
View file @
ce416485
...
...
@@ -59,8 +59,8 @@
</el-col>
</el-row>
<el-row>
<el-col
:span=
"2
.5
"
>
<label
class=
"label-title"
>
事业部
门
负责人:
</label>
<el-col
:span=
"2"
>
<label
class=
"label-title"
>
事业部负责人:
</label>
</el-col>
<el-col
:span=
"2"
>
<span
class=
"label"
>
...
...
@@ -125,9 +125,9 @@
<label
class=
"label-title"
>
项目附件:
</label>
</el-col>
<el-col
:span=
"2"
>
<span
class=
"label"
v-for=
"(item, index) in form.projectAnnexList"
:key=
"index
"
>
<el-link
:href=
"item.fileUrl"
target=
"_blank"
>
{{ item
.fileName }}
</el-link>
</span>
<span
v-for=
"(file, index) in form.projectAnnexList"
:key=
"index"
class=
"file-item
"
>
<el-link
:href=
"file.fileUrl"
target=
"_blank"
>
{{ file
.fileName }}
</el-link>
</span>
</el-col>
</el-row>
<el-row>
...
...
@@ -293,4 +293,11 @@ getUserList()
line-height
:
40px
;
}
.file-item
{
display
:
block
;
margin
:
9px
0
;
}
.file-item
.el-link
{
font-size
:
18px
;
}
</
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