Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
J
jilinzhongdianrenqun-web
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
吴超
jilinzhongdianrenqun-web
Commits
9e3dd30b
Commit
9e3dd30b
authored
Dec 25, 2025
by
zhangtw
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
5fb48cf8
6391ed84
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
384 行增加
和
43 行删除
+384
-43
src/api/key-dm-leave.js
+26
-0
src/api/key-dm-user-permission.js
+54
-0
src/api/key-dm-user.js
+15
-0
src/view/key-person/key_dm_leave/index.vue
+257
-27
src/view/key-person/key_dm_user/index.vue
+32
-16
没有找到文件。
src/api/key-dm-leave.js
View file @
9e3dd30b
...
...
@@ -8,6 +8,14 @@ export const getLeaveList = (param) => {
data
:
param
})
}
// 列表查询(支持分页与筛选)
export
const
getLeaveListByUserId
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmLeave/selectListByUserId'
,
method
:
'post'
,
data
:
param
})
}
// 获取待审核列表
export
const
getPendingList
=
(
param
)
=>
{
...
...
@@ -89,3 +97,20 @@ export const getLeaveStats = (param) => {
data
:
param
})
}
export
const
getLeaveTypeList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmLeaveType/selectList'
,
method
:
'post'
,
data
:
param
})
}
// 转交审批人(前端发起将当前待审批任务转给其他审批人)
export
const
transferLeaveApproval
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmLeave/transferApproval'
,
method
:
'post'
,
data
:
param
})
}
\ No newline at end of file
src/api/key-dm-user-permission.js
0 → 100644
View file @
9e3dd30b
import
axios
from
'@/libs/api.request'
const
permissionType
=
{
// 键:枚举名,值:枚举值(可以是数字/字符串)
LEAVEAPPROVAL
:
"leave_approval"
,
// 请假审核
LEAVEVIEW
:
"leave_view"
,
// 请假查询统计
SUPPLYAPPROVAL
:
"supply_approval"
,
// 用品审核
SUPPLYVIEW
:
"supply_view"
// 用品查询统计
};
// 获取日常人员列表
export
const
getLeaveApprovalPermission
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/selectOrgPermission'
,
method
:
'post'
,
data
:{
permissionType
:
permissionType
.
LEAVEAPPROVAL
}
})
}
// 根据机构编码同步本级及下属机构用户(存在则更新、不存在则新增;null 不覆盖)
export
const
getLeaveView
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/selectOrgPermission'
,
method
:
'post'
,
data
:{
permissionType
:
permissionType
.
LEAVEVIEW
}
})
}
// 保存单个日常人员(前端编辑后保存)
export
const
getSupplyApproval
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/selectOrgPermission'
,
method
:
'post'
,
data
:{
permissionType
:
permissionType
.
SUPPLYAPPROVAL
}
})
}
// 分页查询日常人员可选上级领导列表
export
const
getSupplyView
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/selectOrgPermission'
,
method
:
'post'
,
data
:{
permissionType
:
permissionType
.
SUPPLYVIEW
}
})
}
\ No newline at end of file
src/api/key-dm-user.js
View file @
9e3dd30b
...
...
@@ -36,6 +36,21 @@ export const getUserSelectorList = (param) => {
})
}
// 分页查询日常人员可选上级部门列表
export
const
dmUserOffice
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUser/dmUserOffice'
,
method
:
'post'
,
data
:
param
})
}
export
const
getUserTypeList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
,
})
}
// 获取人员多选器列表(所有在职人员)
export
const
getUserMultiSelectorList
=
(
param
)
=>
{
return
axios
.
request
({
...
...
src/view/key-person/key_dm_leave/index.vue
View file @
9e3dd30b
...
...
@@ -8,6 +8,12 @@
<span>
姓名:
</span>
<Input
v-model=
"filters.apply.name"
placeholder=
"请输入姓名"
style=
"width: 60%"
/>
</Col>
<Col
span=
"8"
>
<span>
审批人:
</span>
<Select
v-model=
"selectedApprovalUser"
style=
"width: 60%"
>
<Option
v-for=
"opt in leaveApprovalOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{
opt
.
name
}}
</Option>
</Select>
</Col>
<Col
span=
"8"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('apply')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('apply')"
>
重置
</Button>
...
...
@@ -32,7 +38,10 @@
<TabPane
label=
"请假待审核"
name=
"pending"
>
<Table
border
:loading=
"loading.pending"
:columns=
"pendingColumns"
:data=
"tables.pending"
>
<
template
slot=
"action"
slot-scope=
"{ row }"
>
<Button
size=
"small"
type=
"primary"
@
click=
"openApproveModal(row)"
>
处理
</Button>
<div
class=
"action-buttons"
>
<Button
size=
"small"
type=
"primary"
@
click=
"openApproveModal(row)"
>
处理
</Button>
<Button
size=
"small"
class=
"mr5"
@
click=
"openTransferModal(row)"
v-if=
"canTransfer(row)"
>
转审核
</Button>
</div>
</
template
>
</Table>
<Page
class=
"page_style"
:total=
"pagers.pending.totalRecord"
:current=
"pagers.pending.pageNo"
:page-size=
"pagers.pending.pageSize"
...
...
@@ -68,7 +77,7 @@
<span>
结束:
</span>
<DatePicker
v-model=
"statsEnd"
type=
"date"
placeholder=
"结束日期"
style=
"min-width:110px;margin-right:20px"
/>
<span>
部门:
</span>
<Input
v-model=
"statsDept"
placeholder=
"请输入部门名称
或ID"
style=
"width: 150px
"
/>
<Input
v-model=
"statsDept"
placeholder=
"请输入部门名称
"
style=
"width:65%
"
/>
</Col>
<Col
span=
"8"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"loadStats"
>
统计
</Button>
...
...
@@ -103,6 +112,11 @@
<FormItem
label=
"紧急电话"
>
<Input
v-model=
"applyModal.form.emergency_phone"
/>
</FormItem>
<FormItem
label=
"指定审批人"
prop=
"approver_id"
>
<Select
v-model=
"applyModal.form.approver_id"
style=
"width: 60%"
>
<Option
v-for=
"opt in leaveApprovalOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{ opt.name }}
</Option>
</Select>
</FormItem>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"applyModal.visible = false"
>
取消
</Button>
...
...
@@ -148,22 +162,38 @@
<Row
class=
"mt8"
><Col
span=
"24"
><p><strong>
起止时间:
</strong>
{{ formatDatetime(detailModal.data.start_time) }} - {{ formatDatetime(detailModal.data.end_time) }}
</p></Col></Row>
<Row
class=
"mt8"
><Col
span=
"24"
><p><strong>
请假事由:
</strong>
{{ detailModal.data.reason || '-' }}
</p></Col></Row>
<Row
class=
"mt8"
><Col
span=
"24"
><h4>
审批记录
</h4></Col></Row>
<Table
:data=
"detailModal.approvals"
size=
"small"
border
>
<TableColumn
title=
"节点"
key=
"node_index"
/>
<TableColumn
title=
"审批人"
key=
"approver_name"
/>
<TableColumn
title=
"结果"
key=
"approver_result"
:render=
"renderApproveResult"
/>
<TableColumn
title=
"时间"
key=
"approver_time"
/>
<TableColumn
title=
"意见"
key=
"comment"
/>
</Table>
<div>
<!-- 详情表格:使用预先定义的列配置渲染 approvals -->
<Table
:data=
"detailModal.approvals"
:columns=
"detailApprovalColumns"
size=
"small"
border
/>
</div>
</div>
<div
slot=
"footer"
><Button
type=
"primary"
@
click=
"detailModal.visible=false"
>
关闭
</Button></div>
</Modal>
<!-- 转审核弹窗 -->
<Modal
v-model=
"transferModal.visible"
title=
"转审核"
width=
"520"
>
<Form
:model=
"transferModal"
:label-width=
"120"
>
<FormItem
label=
"选择审批人"
prop=
"approver_id"
>
<Select
v-model=
"transferModal.selectedApprover"
style=
"width: 60%"
>
<Option
v-for=
"opt in leaveApprovalOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{ opt.name }}
</Option>
</Select>
</FormItem>
<FormItem
label=
"备注(可选)"
>
<Input
type=
"textarea"
v-model=
"transferModal.comment"
:rows=
"3"
placeholder=
"转交备注(选填)"
/>
</FormItem>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"transferModal.visible = false"
>
取消
</Button>
<Button
type=
"primary"
:loading=
"transferModal.processing"
@
click=
"confirmTransfer"
>
确定转交
</Button>
</div>
</Modal>
</div>
</template>
<
script
>
import
{
getLeaveList
,
getLeaveListByUserId
,
saveLeaveApplication
,
submitLeaveApplication
,
revokeLeaveApplication
,
...
...
@@ -172,9 +202,11 @@ import {
rejectLeave
,
getApprovalHistory
,
getLeaveStats
,
getLeaveById
getLeaveById
,
getLeaveTypeList
}
from
'@/api/key-dm-leave'
import
{
getDictList
}
from
'@/api/common'
import
{
transferLeaveApproval
}
from
'@/api/key-dm-leave'
import
{
getLeaveApprovalPermission
}
from
'@/api/key-dm-user-permission'
export
default
{
name
:
'key-dm-leave-index'
,
...
...
@@ -182,6 +214,9 @@ export default {
return
{
activeTab
:
'apply'
,
filters
:
{
apply
:
{
name
:
''
}
},
// 下拉:请假审核权限可选人员
leaveApprovalOptions
:
[],
selectedApprovalUser
:
''
,
tables
:
{
apply
:
[],
pending
:
[],
history
:
[],
query
:
[],
stats
:
[]
},
pagers
:
{
apply
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
pending
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
history
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
query
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
}
},
loading
:
{
apply
:
false
,
pending
:
false
,
history
:
false
,
query
:
false
,
stats
:
false
},
...
...
@@ -193,7 +228,7 @@ export default {
{
title
:
'请假类型'
,
key
:
'leave_type_name'
,
align
:
'center'
},
{
title
:
'起止时间'
,
key
:
'start_time'
,
align
:
'center'
,
render
:
(
h
,
{
row
})
=>
h
(
'span'
,
`
${
row
.
start_time
||
'-'
}
~
${
row
.
end_time
||
'-'
}
`
)
},
{
title
:
'时长'
,
key
:
'duration'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
,
render
:
(
h
,
{
row
})
=>
h
(
'span'
,
this
.
mapStatusText
(
row
.
status
))
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
320
}
],
pendingColumns
:
[
...
...
@@ -215,7 +250,7 @@ export default {
queryColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'申请人'
,
key
:
'user_name'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
,
render
:
(
h
,
{
row
})
=>
h
(
'span'
,
this
.
mapStatusText
(
row
.
status
))
},
{
title
:
'提交时间'
,
key
:
'submit_time'
,
align
:
'center'
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
100
}
],
...
...
@@ -225,8 +260,16 @@ export default {
{
title
:
'部门'
,
key
:
'department_name'
,
align
:
'center'
},
{
title
:
'已通过天数'
,
key
:
'passed_days'
,
align
:
'center'
}
],
detailApprovalColumns
:
[
{
title
:
'节点'
,
key
:
'node_index'
,
align
:
'center'
},
{
title
:
'审批人'
,
key
:
'approver_name'
,
align
:
'center'
},
{
title
:
'结果'
,
key
:
'approver_result'
,
align
:
'center'
,
render
:
(
h
,
{
row
})
=>
h
(
'span'
,
this
.
renderApproveResult
(
h
,
{
row
}))
},
{
title
:
'时间'
,
key
:
'approver_time'
,
align
:
'center'
},
{
title
:
'意见'
,
key
:
'comment'
,
align
:
'center'
}
],
applyModal
:
{
visible
:
false
,
isEdit
:
false
,
saving
:
false
,
form
:
{}
},
approveModal
:
{
visible
:
false
,
record
:
{},
comment
:
''
,
submitting
:
false
},
transferModal
:
{
visible
:
false
,
selectedApprover
:
''
,
comment
:
''
,
processing
:
false
,
record
:
{}
},
detailModal
:
{
visible
:
false
,
loading
:
false
,
data
:
{},
approvals
:
[]
},
statsStart
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
(),
1
),
statsEnd
:
new
Date
(),
...
...
@@ -236,6 +279,7 @@ export default {
created
()
{
this
.
loadLeaveTypes
()
this
.
fetchList
(
'apply'
)
this
.
loadLeaveApprovalOptions
()
},
methods
:
{
handleTabChange
(
name
)
{
...
...
@@ -245,7 +289,7 @@ export default {
if
(
name
===
'query'
)
this
.
fetchList
(
'query'
)
},
fetchList
(
tab
)
{
const
apiMap
=
{
apply
:
getLeaveList
,
pending
:
getPendingList
,
history
:
getApprovalHistory
,
query
:
getLeaveList
}
const
apiMap
=
{
apply
:
getLeaveList
ByUserId
,
pending
:
getPendingList
,
history
:
getApprovalHistory
,
query
:
getLeaveList
}
const
api
=
apiMap
[
tab
]
if
(
!
api
)
return
this
.
loading
[
tab
]
=
true
...
...
@@ -253,42 +297,173 @@ export default {
api
(
payload
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
data
=
ret
.
data
.
data
||
{}
if
(
tab
===
'history'
)
this
.
tables
.
history
=
data
.
results
||
[]
else
if
(
tab
===
'pending'
)
this
.
tables
.
pending
=
data
.
results
||
[]
else
if
(
tab
===
'query'
)
this
.
tables
.
query
=
data
.
results
||
[]
else
this
.
tables
.
apply
=
data
.
results
||
[]
// 后端可能返回时间戳(毫秒)或不同格式,统一转换为可读字符串用于前端展示
const
normalizedResults
=
(
data
.
results
||
[]).
map
(
item
=>
{
if
(
!
item
)
return
item
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
item
,
'start_time'
))
{
item
.
start_time
=
this
.
formatDisplayDatetime
(
item
.
start_time
)
}
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
item
,
'end_time'
))
{
item
.
end_time
=
this
.
formatDisplayDatetime
(
item
.
end_time
)
}
// Normalize approver id/name from various backend key possibilities so the edit modal can reflect the selected approver
item
.
approver_id
=
item
.
approver_id
||
item
.
approverId
||
item
.
transfer_to_id
||
item
.
transferToId
||
item
.
deal_user_id
||
item
.
dealUserId
||
''
item
.
approver_name
=
item
.
approver_name
||
item
.
approverName
||
item
.
transfer_to_name
||
item
.
transferToName
||
item
.
deal_user_name
||
item
.
dealUserName
||
item
.
update_name
||
item
.
update_by_name
||
''
return
item
})
if
(
tab
===
'history'
)
this
.
tables
.
history
=
normalizedResults
else
if
(
tab
===
'pending'
)
this
.
tables
.
pending
=
normalizedResults
else
if
(
tab
===
'query'
)
this
.
tables
.
query
=
normalizedResults
else
this
.
tables
.
apply
=
normalizedResults
if
(
data
.
totalRecord
!==
undefined
)
(
this
.
pagers
[
tab
]
||
{}).
totalRecord
=
data
.
totalRecord
}
else
{
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
finally
(()
=>
{
this
.
loading
[
tab
]
=
false
})
},
/**
* Map numeric approval status codes to human-readable text.
* 0 => 未审批
* 1 => 审核中
* 9 => 审核通过
* other => 显示原始值或通用占位
*/
mapStatusText
(
status
)
{
if
(
status
===
0
||
String
(
status
)
===
'0'
)
return
'未审批'
if
(
status
===
1
||
String
(
status
)
===
'1'
)
return
'审核中'
if
(
status
===
9
||
String
(
status
)
===
'9'
)
return
'审核通过'
if
(
status
===
-
1
||
String
(
status
)
===
'-1'
)
return
'已驳回'
if
(
status
===
null
||
status
===
undefined
||
status
===
''
)
return
'-'
return
String
(
status
)
},
handleSearch
(
tab
)
{
(
this
.
pagers
[
tab
]
||
{}).
pageNo
=
1
;
this
.
fetchList
(
tab
)
},
handleReset
(
tab
)
{
this
.
filters
[
tab
]
=
{};
(
this
.
pagers
[
tab
]
||
{}).
pageNo
=
1
;
this
.
fetchList
(
tab
)
},
pageChange
(
tab
,
pageNo
)
{
(
this
.
pagers
[
tab
]
||
{}).
pageNo
=
pageNo
;
this
.
fetchList
(
tab
)
},
sizeChange
(
tab
,
size
)
{
(
this
.
pagers
[
tab
]
||
{}).
pageSize
=
size
;
(
this
.
pagers
[
tab
]
||
{}).
pageNo
=
1
;
this
.
fetchList
(
tab
)
},
loadLeaveTypes
()
{
getDictList
({
type
:
'leave_type'
}).
then
(
res
=>
{
let
list
=
res
.
data
if
(
list
)
{
list
=
(
res
.
data
.
data
||
res
.
data
.
results
)
||
[]
getLeaveTypeList
().
then
(
res
=>
{
const
data
=
res
&&
res
.
data
let
results
=
[]
if
(
Array
.
isArray
(
data
))
{
results
=
data
}
else
if
(
data
)
{
if
(
Array
.
isArray
(
data
.
results
))
results
=
data
.
results
else
if
(
Array
.
isArray
(
data
.
data
))
results
=
data
.
data
else
if
(
data
.
data
&&
Array
.
isArray
(
data
.
data
.
results
))
results
=
data
.
data
.
results
}
// Map results into the shape used by the select
this
.
leaveTypes
=
results
.
map
(
it
=>
({
id
:
it
.
id
,
type_name
:
it
.
type_name
}))
}).
catch
(
err
=>
{
// 保持简洁的错误输出,避免抛出未捕获异常
console
.
error
(
'loadLeaveTypes error'
,
err
)
})
},
loadLeaveApprovalOptions
()
{
// 从后端获取有请假审批权限的机构/人员列表,并映射为 { id, name } 供 Select 使用
getLeaveApprovalPermission
().
then
(
res
=>
{
const
d
=
res
&&
res
.
data
let
results
=
[]
if
(
Array
.
isArray
(
d
))
results
=
d
else
if
(
d
)
{
if
(
Array
.
isArray
(
d
.
results
))
results
=
d
.
results
else
if
(
Array
.
isArray
(
d
.
data
))
results
=
d
.
data
else
if
(
d
.
data
&&
Array
.
isArray
(
d
.
data
.
results
))
results
=
d
.
data
.
results
}
this
.
leaveTypes
=
Array
.
isArray
(
list
)
?
list
.
map
(
it
=>
({
id
:
it
.
value
||
it
.
dictValue
,
type_name
:
it
.
label
||
it
.
name
}))
:
[]
this
.
leaveApprovalOptions
=
(
results
||
[]).
map
(
it
=>
{
return
{
id
:
it
.
user_id
||
it
.
id
||
it
.
userId
||
''
,
name
:
it
.
user_name
||
it
.
name
||
it
.
userName
||
it
.
nick
||
''
}
})
}).
catch
(
err
=>
{
console
.
error
(
'loadLeaveApprovalOptions error'
,
err
)
})
},
formatForDbDatetime
(
val
)
{
if
(
val
===
null
||
val
===
undefined
||
val
===
''
)
return
val
let
d
=
val
if
(
typeof
val
===
'string'
)
{
// 处理带 T 的 ISO 字符串或其他可解析字符串
d
=
new
Date
(
val
)
}
if
(
!
(
d
instanceof
Date
)
||
isNaN
(
d
.
getTime
()))
{
// 如果无法解析,直接返回原值(后端可进一步校验)
return
val
}
const
pad
=
(
n
)
=>
(
n
<
10
?
'0'
+
n
:
String
(
n
))
return
d
.
getFullYear
()
+
'-'
+
pad
(
d
.
getMonth
()
+
1
)
+
'-'
+
pad
(
d
.
getDate
())
+
' '
+
pad
(
d
.
getHours
())
+
':'
+
pad
(
d
.
getMinutes
())
+
':'
+
pad
(
d
.
getSeconds
())
},
formatDisplayDatetime
(
val
)
{
if
(
val
===
null
||
val
===
undefined
||
val
===
''
)
return
'-'
// 数字(毫秒)
if
(
typeof
val
===
'number'
)
return
this
.
formatForDbDatetime
(
new
Date
(
val
))
// 纯数字字符串(可能是时间戳)
if
(
typeof
val
===
'string'
&&
/^
\d
+$/
.
test
(
val
))
{
try
{
return
this
.
formatForDbDatetime
(
new
Date
(
Number
(
val
)))
}
catch
(
e
)
{
return
val
}
}
// ISO 字符串带 T
if
(
typeof
val
===
'string'
&&
val
.
includes
(
'T'
))
return
this
.
formatDatetime
(
val
)
// 尝试解析为 Date
const
parsed
=
new
Date
(
val
)
if
(
!
isNaN
(
parsed
.
getTime
()))
return
this
.
formatForDbDatetime
(
parsed
)
return
val
},
openApplyModal
()
{
this
.
applyModal
.
isEdit
=
false
this
.
applyModal
.
form
=
{
user_id
:
''
,
user_name
:
''
,
leave_type_id
:
''
,
start_time
:
''
,
end_time
:
''
,
duration_unit
:
2
,
duration
:
0
,
reason
:
''
,
emergency_contact
:
''
,
emergency_phone
:
''
}
this
.
applyModal
.
form
=
{
user_id
:
''
,
user_name
:
''
,
leave_type_id
:
''
,
start_time
:
''
,
end_time
:
''
,
duration_unit
:
2
,
duration
:
0
,
reason
:
''
,
emergency_contact
:
''
,
emergency_phone
:
''
,
approver_id
:
this
.
selectedApprovalUser
||
''
}
this
.
applyModal
.
visible
=
true
},
openEdit
(
row
)
{
this
.
applyModal
.
isEdit
=
true
this
.
applyModal
.
form
=
Object
.
assign
({},
row
)
// ensure approver_id exists on form when editing
if
(
!
this
.
applyModal
.
form
.
approver_id
)
this
.
applyModal
.
form
.
approver_id
=
row
.
approver_id
||
row
.
approverId
||
row
.
transfer_to_id
||
''
this
.
applyModal
.
visible
=
true
},
saveApply
()
{
this
.
applyModal
.
saving
=
true
saveLeaveApplication
(
this
.
applyModal
.
form
).
then
(
ret
=>
{
// 验证开始/结束时间:结束时间必须大于开始时间
const
form
=
this
.
applyModal
.
form
||
{}
const
parseToDate
=
(
v
)
=>
{
if
(
v
===
null
||
v
===
undefined
||
v
===
''
)
return
null
if
(
typeof
v
===
'number'
)
return
new
Date
(
v
)
if
(
typeof
v
===
'string'
)
{
if
(
/^
\d
+$/
.
test
(
v
))
return
new
Date
(
Number
(
v
))
// 把 "YYYY-MM-DD HH:mm:ss" 之类的字符串转换为可解析的 ISO 风格(替换第一个空格为'T')
const
s
=
v
.
includes
(
'T'
)
?
v
:
v
.
replace
(
' '
,
'T'
)
const
parsed
=
new
Date
(
s
)
return
isNaN
(
parsed
.
getTime
())
?
null
:
parsed
}
if
(
v
instanceof
Date
)
return
isNaN
(
v
.
getTime
())
?
null
:
v
const
parsed
=
new
Date
(
v
)
return
isNaN
(
parsed
.
getTime
())
?
null
:
parsed
}
const
startDate
=
parseToDate
(
form
.
start_time
)
const
endDate
=
parseToDate
(
form
.
end_time
)
if
(
startDate
&&
endDate
)
{
if
(
endDate
.
getTime
()
<=
startDate
.
getTime
())
{
this
.
applyModal
.
saving
=
false
this
.
$Message
.
warning
(
'结束时间必须大于开始时间'
)
return
}
}
// 拷贝表单并格式化开始/结束时间为数据库 datetime 字符串
const
payload
=
Object
.
assign
({},
this
.
applyModal
.
form
)
// 同时把审批人姓名一并传回后端(优先使用表单中的 approver_id,否则使用页面选中的 selectedApprovalUser)
const
approverId
=
payload
.
approver_id
||
this
.
selectedApprovalUser
||
''
const
approverOption
=
(
this
.
leaveApprovalOptions
||
[]).
find
(
opt
=>
opt
.
id
===
approverId
)
payload
.
approver_name
=
approverOption
?
approverOption
.
name
:
(
payload
.
approver_name
||
''
)
if
(
payload
.
start_time
)
payload
.
start_time
=
this
.
formatForDbDatetime
(
payload
.
start_time
)
if
(
payload
.
end_time
)
payload
.
end_time
=
this
.
formatForDbDatetime
(
payload
.
end_time
)
saveLeaveApplication
(
payload
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'保存成功'
)
this
.
applyModal
.
visible
=
false
...
...
@@ -318,6 +493,41 @@ export default {
this
.
approveModal
.
comment
=
''
this
.
approveModal
.
visible
=
true
},
canTransfer
(
row
)
{
// 仅当当前为审批中(status === 1)时允许转交;可根据需求调整条件
return
row
&&
(
row
.
status
===
1
||
String
(
row
.
status
)
===
'1'
)
},
openTransferModal
(
row
)
{
this
.
transferModal
.
record
=
Object
.
assign
({},
row
)
// 默认选择当前审批人(如果有)
this
.
transferModal
.
selectedApprover
=
row
.
approver_id
||
row
.
approverId
||
row
.
transfer_to_id
||
''
this
.
transferModal
.
comment
=
''
this
.
transferModal
.
visible
=
true
},
confirmTransfer
()
{
if
(
!
this
.
transferModal
.
selectedApprover
)
{
this
.
$Message
.
warning
(
'请选择要转交的审批人'
)
return
}
this
.
transferModal
.
processing
=
true
const
approverOption
=
(
this
.
leaveApprovalOptions
||
[]).
find
(
opt
=>
opt
.
id
===
this
.
transferModal
.
selectedApprover
)
const
payload
=
{
id
:
this
.
transferModal
.
record
.
id
,
approver_id
:
this
.
transferModal
.
selectedApprover
,
approver_name
:
approverOption
?
approverOption
.
name
:
''
,
comment
:
this
.
transferModal
.
comment
||
''
}
transferLeaveApproval
(
payload
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'转交成功'
)
this
.
transferModal
.
visible
=
false
// 刷新待办列表
this
.
fetchList
(
'pending'
)
}
else
{
this
.
$Notice
.
error
({
title
:
'转交失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
finally
(()
=>
{
this
.
transferModal
.
processing
=
false
})
},
confirmApprove
()
{
this
.
approveModal
.
submitting
=
true
approveLeave
({
id
:
this
.
approveModal
.
record
.
id
,
comment
:
this
.
approveModal
.
comment
}).
then
(
ret
=>
{
...
...
@@ -336,8 +546,26 @@ export default {
this
.
detailModal
.
loading
=
true
getLeaveById
({
id
:
row
.
id
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
detailModal
.
data
=
ret
.
data
.
data
||
{}
this
.
detailModal
.
approvals
=
ret
.
data
.
data
.
approvals
||
[]
const
respData
=
ret
.
data
.
data
||
{}
this
.
detailModal
.
data
=
respData
// 优先使用 subTables 中的 approvalRecords(如果存在),否则使用 respData.approvals
let
approvals
=
[]
if
(
respData
.
subTables
&&
Array
.
isArray
(
respData
.
subTables
.
approvalRecords
))
{
approvals
=
respData
.
subTables
.
approvalRecords
.
slice
()
}
else
{
approvals
=
respData
.
approvals
||
[]
}
if
(
!
Array
.
isArray
(
approvals
))
approvals
=
[]
approvals
=
approvals
.
map
(
item
=>
{
const
nodeIndex
=
Number
(
item
&&
(
item
.
node_index
||
item
.
nodeIndex
))
return
Object
.
assign
({},
item
,
{
node_index
:
isNaN
(
nodeIndex
)
?
0
:
nodeIndex
,
approver_time
:
this
.
formatDisplayDatetime
(
item
?
item
.
approver_time
:
null
),
approver_name
:
item
?
(
item
.
approver_name
||
item
.
approverName
||
''
)
:
''
})
})
approvals
.
sort
((
a
,
b
)
=>
(
a
.
node_index
||
0
)
-
(
b
.
node_index
||
0
))
this
.
detailModal
.
approvals
=
approvals
}
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}).
finally
(()
=>
{
this
.
detailModal
.
loading
=
false
})
},
...
...
@@ -353,6 +581,7 @@ export default {
}
getLeaveStats
({
params
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
console
.
log
(
"ret.data.data"
,
ret
.
data
.
data
)
this
.
tables
.
stats
=
ret
.
data
.
data
||
[]
}
else
{
this
.
$Notice
.
error
({
title
:
'统计失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
...
...
@@ -377,4 +606,5 @@ export default {
.text-right
{
text-align
:
right
;
}
.page_style
{
margin-top
:
12px
;
text-align
:
right
;
}
.mt8
{
margin-top
:
8px
;
}
.action-buttons
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
justify-content
:
center
;
}
</
style
>
src/view/key-person/key_dm_user/index.vue
View file @
9e3dd30b
...
...
@@ -41,27 +41,25 @@
<
FormItem
label
=
"工号"
>
<
Input
v
-
model
=
"editModal.form.gh"
disabled
/>
<
/FormItem
>
<
FormItem
label
=
"邮箱"
>
<
Input
v
-
model
=
"editModal.form.email"
/>
<
/FormItem
>
<
FormItem
label
=
"电话"
>
<
Input
v
-
model
=
"editModal.form.phone"
/>
<
/FormItem
>
<
FormItem
label
=
"手机"
>
<
Input
v
-
model
=
"editModal.form.mobile"
/>
<
/FormItem
>
<
FormItem
label
=
"出生日期"
>
<
!--
<
FormItem
label
=
"出生日期"
>
<
DatePicker
v
-
model
=
"editModal.form.birthday"
type
=
"date"
placeholder
=
"请选择日期"
/>
<
/FormItem
>
<
/FormItem>
--
>
<
FormItem
label
=
"参加工作时间"
>
<
DatePicker
v
-
model
=
"editModal.form.in_work_time"
type
=
"date"
placeholder
=
"请选择日期"
/>
<
/FormItem
>
<
FormItem
label
=
"归属部门"
>
<
Input
v
-
model
=
"editModal.form.office_id"
placeholder
=
"请输入机构ID(可通过列表选择扩展)"
/>
<
/FormItem
>
<
FormItem
label
=
"直属领导ID"
>
<
Input
v
-
model
=
"editModal.form.leader"
placeholder
=
"只能选择本级或父机构人员ID"
/>
<!--
角色已移除
-->
<!--
<
FormItem
label
=
"归属部门"
>
<
SelectDisplay
v
-
model
=
"editModal.form.office_id"
placeholder
=
"请输入机构"
@
open
=
"openOfficeSelect(editModal.form)"
/>
<
/FormItem
>
<
FormItem
label
=
"直属领导"
>
<
SelectDisplay
v
-
model
=
"editModal.form.leader"
placeholder
=
"只能选择本级或父机构人员"
@
open
=
"openSelectLeader(editModal.form)"
/>
<
/FormItem> --
>
<
FormItem
label
=
"是否离职"
>
<
Select
v
-
model
=
"editModal.form.is_leave"
style
=
"width: 160px"
>
<
Option
:
value
=
"0"
>
未离职
<
/Option
>
...
...
@@ -74,6 +72,7 @@
<
Button
type
=
"primary"
:
loading
=
"editModal.saving"
@
click
=
"saveEdit"
>
保存
<
/Button
>
<
/div
>
<
/Modal
>
<!--
领导与归属部门选择已移除
-->
<
/div
>
<
/template
>
...
...
@@ -82,22 +81,21 @@ import { getDmUserList, syncDmUsersByOffice, saveDmUser } from '@/api/key-dm-use
export
default
{
name
:
'key-dm-user-index'
,
components
:
{
}
,
data
()
{
return
{
officeCode
:
''
,
filters
:
{
name
:
''
}
,
rows
:
[],
// leaders/userTypes 已移除
loading
:
false
,
columns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
}
,
{
title
:
'姓名'
,
key
:
'name'
,
align
:
'center'
}
,
{
title
:
'工号'
,
key
:
'gh'
,
align
:
'center'
}
,
{
title
:
'归属部门'
,
key
:
'office_name'
,
align
:
'center'
}
,
{
title
:
'邮箱'
,
key
:
'email'
,
align
:
'center'
}
,
{
title
:
'电话'
,
key
:
'phone'
,
align
:
'center'
}
,
{
title
:
'手机'
,
key
:
'mobile'
,
align
:
'center'
}
,
{
title
:
'离职'
,
key
:
'is_leave'
,
slot
:
'is_leave'
,
width
:
80
,
align
:
'center'
}
,
{
title
:
'同步来源'
,
key
:
'is_ext'
,
slot
:
'is_ext'
,
width
:
120
,
align
:
'center'
}
,
{
title
:
'操作'
,
slot
:
'action'
,
width
:
200
,
align
:
'center'
}
],
pager
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
}
,
...
...
@@ -105,7 +103,8 @@ export default {
visible
:
false
,
saving
:
false
,
form
:
{
}
}
}
,
// leader / office state 已移除
}
}
,
created
()
{
...
...
@@ -125,7 +124,19 @@ export default {
console
.
log
(
'getDmUserList'
,
ret
)
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
data
=
ret
.
data
.
data
||
{
}
this
.
rows
=
data
.
results
||
[]
this
.
rows
=
(
data
.
results
||
[]).
map
(
row
=>
{
// 规范化后端返回的大写 Id 到前端统一使用小写 id(作为主键)
const
copy
=
Object
.
assign
({
}
,
row
)
if
(
copy
.
Id
!=
null
&&
copy
.
id
==
null
)
copy
.
id
=
copy
.
Id
// 处理嵌套对象可能带有 Id 的情况(归属机构/领导)
if
(
copy
.
office_id
&&
copy
.
office_id
.
Id
!=
null
&&
copy
.
office_id
.
id
==
null
)
{
copy
.
office_id
=
Object
.
assign
({
}
,
copy
.
office_id
,
{
id
:
copy
.
office_id
.
Id
}
)
}
if
(
copy
.
leader
&&
copy
.
leader
.
Id
!=
null
&&
copy
.
leader
.
id
==
null
)
{
copy
.
leader
=
Object
.
assign
({
}
,
copy
.
leader
,
{
id
:
copy
.
leader
.
Id
}
)
}
return
copy
}
)
this
.
pager
.
totalRecord
=
data
.
totalRecord
||
0
console
.
log
(
'data'
,
this
.
rows
)
}
else
{
...
...
@@ -133,6 +144,7 @@ export default {
}
}
).
finally
(()
=>
{
this
.
loading
=
false
}
)
}
,
/* 用户角色加载已移除 */
handleSearch
()
{
this
.
pager
.
pageNo
=
1
this
.
fetchList
()
...
...
@@ -170,9 +182,13 @@ export default {
}
)
}
,
openEdit
(
row
)
{
this
.
editModal
.
form
=
Object
.
assign
({
}
,
row
)
// 直接拷贝记录用于编辑,并保证小写 id 可用
const
copy
=
Object
.
assign
({
}
,
row
)
if
(
copy
.
Id
!=
null
&&
copy
.
id
==
null
)
copy
.
id
=
copy
.
Id
this
.
editModal
.
form
=
copy
this
.
editModal
.
visible
=
true
}
,
/* leader / office 相关方法已移除 */
saveEdit
()
{
this
.
$refs
.
editForm
.
validate
(
valid
=>
{
// no strict validation here, just save
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论