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
7452feec
Commit
7452feec
authored
Dec 30, 2025
by
zhangtw
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://code.palacesun.com/wuchao/jilinzhongdianrenqun-web
parents
e5b5fb79
f4fa16c1
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
1089 行增加
和
165 行删除
+1089
-165
src/api/key-dm-user.js
+3
-2
src/api/key-dm.js
+74
-0
src/router/group/key-person.js
+8
-0
src/view/key-person/key_dm_conf/chartAnalysis.vue
+471
-0
src/view/key-person/key_dm_conf/index.vue
+226
-60
src/view/key-person/key_dm_inventory/stats.vue
+111
-67
src/view/key-person/key_dm_leave/index.vue
+13
-18
src/view/key-person/key_dm_user/index.vue
+28
-8
src/view/key-person/key_dm_user/userMultiSelector.vue
+8
-10
src/view/key-person/key_dm_user/userSelector.vue
+147
-0
没有找到文件。
src/api/key-dm-user.js
View file @
7452feec
...
...
@@ -47,8 +47,9 @@ export const dmUserOffice = (param) => {
export
const
getUserTypeList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
,
method
:
'post'
,
data
:
param
})
}
// 获取人员多选器列表(所有在职人员)
...
...
src/api/key-dm.js
View file @
7452feec
...
...
@@ -167,3 +167,77 @@ export const getWorkloadDetails = (param) => {
data
:
param
})
}
// ===== 图表分析 =====
// 汇总统计数据
export
const
getSummaryStats
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/getSummaryStats'
,
method
:
'post'
})
}
// 请假类型统计
export
const
getLeaveTypeStats
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/getLeaveTypeStats'
,
method
:
'post'
})
}
// 人员请假统计
export
const
getLeaveUserStats
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/getLeaveUserStats'
,
method
:
'post'
})
}
// 用品领用统计
export
const
getMaterialUsageStats
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/getMaterialUsageStats'
,
method
:
'post'
})
}
// 库存预警列表
export
const
getStockWarningList
=
()
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/getStockWarningList'
,
method
:
'post'
})
}
// ===== 部门管理 =====
export
const
getOrgList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectOrgList'
,
method
:
'post'
,
data
:
param
})
}
export
const
saveOrg
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/saveOrg'
,
method
:
'post'
,
data
:
param
})
}
export
const
deleteOrg
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/deleteOrg'
,
method
:
'post'
,
data
:
param
})
}
export
const
assignUsersToOrg
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/assignUsersToOrg'
,
method
:
'post'
,
data
:
param
})
}
src/router/group/key-person.js
View file @
7452feec
...
...
@@ -254,5 +254,13 @@ export default [
title
:
'日常管理统计'
},
component
:
()
=>
import
(
'@/view/key-person/key_dm_inventory/stats'
)
},
{
path
:
'/key-person/dmChartAnalysis'
,
name
:
'dmChartAnalysis'
,
meta
:
{
title
:
'日常数据统计分析'
},
component
:
()
=>
import
(
'@/view/key-person/key_dm_conf/chartAnalysis'
)
}
]
src/view/key-person/key_dm_conf/chartAnalysis.vue
0 → 100644
View file @
7452feec
<
template
>
<div
class=
"chart-analysis-wrapper"
>
<!-- 第一行:统计标签 -->
<div
class=
"header-container"
>
<div
class=
"title-wrapper"
>
<div
class=
"title-bar"
></div>
<h3
class=
"title-text"
>
数据概览
</h3>
</div>
</div>
<Row
class=
"statistics-bar"
>
<Col
span=
"8"
>
<div
class=
"statistics-item leave-count"
>
<div
class=
"stat-icon"
>
<Icon
type=
"ios-calendar-outline"
size=
"32"
/>
</div>
<div
class=
"stat-content"
>
<div
class=
"stat-title"
>
请假申请次数
</div>
<div
class=
"stat-number"
>
{{
summaryData
.
leaveCount
}}
</div>
<div
class=
"stat-unit"
>
次
</div>
</div>
</div>
</Col>
<Col
span=
"8"
>
<div
class=
"statistics-item borrow-count"
>
<div
class=
"stat-icon"
>
<Icon
type=
"ios-paper-outline"
size=
"32"
/>
</div>
<div
class=
"stat-content"
>
<div
class=
"stat-title"
>
办公用品申领次数
</div>
<div
class=
"stat-number"
>
{{
summaryData
.
borrowCount
}}
</div>
<div
class=
"stat-unit"
>
次
</div>
</div>
</div>
</Col>
<Col
span=
"8"
>
<div
class=
"statistics-item inbound-count"
>
<div
class=
"stat-icon"
>
<Icon
type=
"ios-archive-outline"
size=
"32"
/>
</div>
<div
class=
"stat-content"
>
<div
class=
"stat-title"
>
办公用品入库次数
</div>
<div
class=
"stat-number"
>
{{
summaryData
.
inboundCount
}}
</div>
<div
class=
"stat-unit"
>
次
</div>
</div>
</div>
</Col>
</Row>
<!-- 第二行:请假相关图表 -->
<div
class=
"header-container"
>
<div
class=
"title-wrapper"
>
<div
class=
"title-bar"
></div>
<h3
class=
"title-text"
>
请假数据分析
</h3>
</div>
</div>
<Row
:gutter=
"16"
>
<Col
span=
"10"
>
<Card>
<div
class=
"chart-title"
>
请假类型占比
</div>
<div
ref=
"leaveTypeChart"
class=
"chart-container"
></div>
</Card>
</Col>
<Col
span=
"14"
>
<Card>
<div
class=
"chart-title"
>
月度各人员请假次数
</div>
<div
ref=
"leaveUserChart"
class=
"chart-container"
></div>
</Card>
</Col>
</Row>
<!-- 第三行:办公用品相关图表和表格 -->
<div
class=
"header-container"
>
<div
class=
"title-wrapper"
>
<div
class=
"title-bar"
></div>
<h3
class=
"title-text"
>
办公用品数据分析
</h3>
</div>
</div>
<Row
:gutter=
"16"
>
<Col
span=
"10"
>
<Card>
<div
class=
"chart-title"
>
月度各用品领用量
</div>
<div
ref=
"materialUsageChart"
class=
"chart-container"
></div>
</Card>
</Col>
<Col
span=
"14"
>
<Card
class=
"stock-warning-card"
>
<div
class=
"chart-title"
>
库存预警信息
</div>
<div
class=
"table-container"
>
<Table
:data=
"stockWarningData"
:columns=
"stockWarningColumns"
size=
"small"
border
:height=
"chartHeight"
>
<template
slot=
"threshold"
slot-scope=
"
{ row }">
<span>
{{
row
.
min_stock
}}
-
{{
row
.
max_stock
}}
</span>
</
template
>
<
template
slot=
"status"
slot-scope=
"{ row }"
>
<Tag
:color=
"row.status === 'low' ? 'red' : 'orange'"
>
{{
row
.
status
===
'low'
?
'库存不足'
:
'库存过高'
}}
</Tag>
</
template
>
</Table>
</div>
</Card>
</Col>
</Row>
</div>
</template>
<
script
>
import
*
as
echarts
from
'echarts'
import
{
getSummaryStats
,
getLeaveTypeStats
,
getLeaveUserStats
,
getMaterialUsageStats
,
getStockWarningList
}
from
'@/api/key-dm'
export
default
{
name
:
'chart-analysis'
,
data
()
{
return
{
summaryData
:
{
leaveCount
:
0
,
borrowCount
:
0
,
inboundCount
:
0
},
leaveTypeChart
:
null
,
leaveUserChart
:
null
,
materialUsageChart
:
null
,
chartHeight
:
240
,
stockWarningData
:
[],
stockWarningColumns
:
[
{
title
:
'用品名称'
,
key
:
'material_name'
,
align
:
'center'
,
minWidth
:
50
},
{
title
:
'现有数量'
,
key
:
'available_quantity'
,
align
:
'center'
,
minWidth
:
50
},
{
title
:
'阙值范围'
,
slot
:
'threshold'
,
align
:
'center'
,
minWidth
:
50
},
{
title
:
'状态'
,
slot
:
'status'
,
align
:
'center'
,
minWidth
:
50
}
]
}
},
mounted
()
{
this
.
loadData
()
},
beforeDestroy
()
{
if
(
this
.
leaveTypeChart
)
{
this
.
leaveTypeChart
.
dispose
()
}
if
(
this
.
leaveUserChart
)
{
this
.
leaveUserChart
.
dispose
()
}
if
(
this
.
materialUsageChart
)
{
this
.
materialUsageChart
.
dispose
()
}
},
methods
:
{
loadData
()
{
this
.
loadSummaryStats
()
this
.
loadLeaveTypeStats
()
this
.
loadLeaveUserStats
()
this
.
loadMaterialUsageStats
()
this
.
loadStockWarningList
()
},
loadSummaryStats
()
{
getSummaryStats
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
summaryData
=
ret
.
data
.
data
||
this
.
summaryData
}
}).
catch
(()
=>
{
this
.
$Message
.
error
(
'获取统计数据失败'
)
})
},
loadLeaveTypeStats
()
{
getLeaveTypeStats
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
initLeaveTypeChart
(
ret
.
data
.
data
||
[])
}
}).
catch
(()
=>
{
this
.
$Message
.
error
(
'获取请假类型统计失败'
)
})
},
loadLeaveUserStats
()
{
getLeaveUserStats
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
initLeaveUserChart
(
ret
.
data
.
data
||
[])
}
}).
catch
(()
=>
{
this
.
$Message
.
error
(
'获取人员请假统计失败'
)
})
},
loadMaterialUsageStats
()
{
getMaterialUsageStats
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
initMaterialUsageChart
(
ret
.
data
.
data
||
[])
}
}).
catch
(()
=>
{
this
.
$Message
.
error
(
'获取用品领用统计失败'
)
})
},
loadStockWarningList
()
{
getStockWarningList
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
stockWarningData
=
ret
.
data
.
data
||
[]
}
}).
catch
(()
=>
{
this
.
$Message
.
error
(
'获取库存预警数据失败'
)
})
},
initLeaveTypeChart
(
data
)
{
this
.
$nextTick
(()
=>
{
const
chartDom
=
this
.
$refs
.
leaveTypeChart
if
(
!
chartDom
)
return
this
.
leaveTypeChart
=
echarts
.
init
(
chartDom
)
const
colors
=
[
'#73c0de'
,
'#3ba272'
,
'#fc8452'
,
'#9a60b4'
,
'#ea7ccc'
,
'#91cc75'
,
'#fac858'
,
'#ee6666'
]
const
option
=
{
tooltip
:
{
trigger
:
'item'
,
formatter
:
'{a} <br/>{b}: {c} ({d}%)'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
,
textStyle
:
{
fontSize
:
12
}
},
color
:
colors
,
series
:
[
{
name
:
'请假类型'
,
type
:
'pie'
,
radius
:
[
'50%'
,
'70%'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
true
,
position
:
'outside'
,
formatter
:
'{b}: {c}'
,
fontSize
:
12
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
'16'
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
true
,
length
:
10
,
length2
:
10
},
data
:
data
.
map
((
item
,
index
)
=>
({
value
:
item
.
count
,
name
:
item
.
type_name
,
itemStyle
:
{
color
:
colors
[
index
%
colors
.
length
]
}
}))
}
]
}
this
.
leaveTypeChart
.
setOption
(
option
)
})
},
initLeaveUserChart
(
data
)
{
this
.
$nextTick
(()
=>
{
const
chartDom
=
this
.
$refs
.
leaveUserChart
if
(
!
chartDom
)
return
this
.
leaveUserChart
=
echarts
.
init
(
chartDom
)
const
option
=
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
grid
:
{
left
:
'3%'
,
right
:
'4%'
,
bottom
:
'3%'
,
containLabel
:
true
},
xAxis
:
{
type
:
'category'
,
data
:
data
.
map
(
item
=>
item
.
user_name
),
axisLabel
:
{
rotate
:
45
}
},
yAxis
:
{
type
:
'value'
},
series
:
[
{
name
:
'请假次数'
,
type
:
'bar'
,
data
:
data
.
map
(
item
=>
item
.
leave_count
),
itemStyle
:
{
color
:
'#409EFF'
}
}
]
}
this
.
leaveUserChart
.
setOption
(
option
)
})
},
initMaterialUsageChart
(
data
)
{
this
.
$nextTick
(()
=>
{
const
chartDom
=
this
.
$refs
.
materialUsageChart
if
(
!
chartDom
)
return
this
.
materialUsageChart
=
echarts
.
init
(
chartDom
)
const
colors
=
[
'#73c0de'
,
'#3ba272'
,
'#fc8452'
,
'#9a60b4'
,
'#ea7ccc'
,
'#91cc75'
,
'#fac858'
,
'#ee6666'
]
const
option
=
{
tooltip
:
{
trigger
:
'item'
,
formatter
:
'{a} <br/>{b}: {c} ({d}%)'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
,
textStyle
:
{
fontSize
:
12
}
},
color
:
colors
,
series
:
[
{
name
:
'领用量'
,
type
:
'pie'
,
radius
:
[
'50%'
,
'70%'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
true
,
position
:
'outside'
,
formatter
:
'{b}: {c}'
,
fontSize
:
12
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
'16'
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
true
,
length
:
10
,
length2
:
10
},
data
:
data
.
map
((
item
,
index
)
=>
({
value
:
item
.
total_quantity
,
name
:
item
.
material_name
,
itemStyle
:
{
color
:
colors
[
index
%
colors
.
length
]
}
}))
}
]
}
this
.
materialUsageChart
.
setOption
(
option
)
})
}
}
}
</
script
>
<
style
scoped
>
.chart-analysis-wrapper
{
padding
:
20px
;
}
.header-container
{
margin
:
20px
0
10px
0
;
}
.title-wrapper
{
display
:
flex
;
align-items
:
center
;
}
.title-bar
{
width
:
4px
;
height
:
20px
;
background-color
:
#409EFF
;
margin-right
:
10px
;
}
.title-text
{
margin
:
0
;
font-size
:
18px
;
font-weight
:
600
;
color
:
#333
;
}
.statistics-bar
{
margin-bottom
:
20px
;
}
.statistics-item
{
display
:
flex
;
align-items
:
center
;
padding
:
20px
;
background
:
linear-gradient
(
135deg
,
#667eea
0%
,
#764ba2
100%
);
border-radius
:
8px
;
margin
:
0
10px
;
box-shadow
:
0
4px
6px
rgba
(
0
,
0
,
0
,
0.1
);
}
.statistics-item.leave-count
{
background
:
linear-gradient
(
135deg
,
#f093fb
0%
,
#f5576c
100%
);
}
.statistics-item.borrow-count
{
background
:
linear-gradient
(
135deg
,
#4facfe
0%
,
#00f2fe
100%
);
}
.statistics-item.inbound-count
{
background
:
linear-gradient
(
135deg
,
#43e97b
0%
,
#38f9d7
100%
);
}
.stat-icon
{
color
:
white
;
margin-right
:
20px
;
}
.stat-content
{
flex
:
1
;
}
.stat-title
{
font-size
:
14px
;
color
:
rgba
(
255
,
255
,
255
,
0.8
);
margin-bottom
:
8px
;
}
.stat-number
{
font-size
:
36px
;
font-weight
:
bold
;
color
:
white
;
margin-bottom
:
4px
;
display
:
inline
;
}
.stat-unit
{
font-size
:
16px
;
color
:
rgba
(
255
,
255
,
255
,
0.8
);
display
:
inline
;
}
.chart-container
{
width
:
100%
;
height
:
240px
;
}
.chart-title
{
font-size
:
16px
;
font-weight
:
600
;
margin-bottom
:
16px
;
text-align
:
center
;
}
.stock-warning-card
{
height
:
315px
;
display
:
flex
;
flex-direction
:
column
;
}
.table-container
{
flex
:
1
;
overflow
:
hidden
;
}
</
style
>
src/view/key-person/key_dm_conf/index.vue
View file @
7452feec
...
...
@@ -9,17 +9,51 @@
</
template
>
</Table>
</TabPane>
<!-- 部门管理 -->
<TabPane
label=
"部门管理"
name=
"org"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"12"
>
<span>
部门名称:
</span>
<Input
v-model=
"filters.org.org_name"
placeholder=
"请输入"
style=
"width: 200px"
/>
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('org')"
>
搜索
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleReset('org')"
>
重置
</Button>
<Button
type=
"primary"
@
click=
"openAddModal('org')"
>
新增
</Button>
</Col>
</Row>
</div>
<Table
border
:loading=
"loading.org"
:columns=
"orgColumns"
:data=
"tables.org"
>
<
template
slot=
"action"
slot-scope=
"{ row }"
>
<Button
size=
"small"
type=
"primary"
class=
"mr5"
@
click=
"openEditModal('org', row)"
>
修改
</Button>
<Button
size=
"small"
type=
"info"
class=
"mr5"
@
click=
"openUserAssignModal(row)"
>
人员划分
</Button>
<Poptip
confirm
title=
"确认删除?"
transfer
@
on-ok=
"handleDelete('org', row)"
>
<Button
size=
"small"
type=
"error"
>
删除
</Button>
</Poptip>
</
template
>
</Table>
<Page
class=
"page_style"
:total=
"pagers.org.totalRecord"
:current=
"pagers.org.pageNo"
:page-size=
"pagers.org.pageSize"
show-total
show-sizer
@
on-change=
"pageChange('org', $event)"
@
on-page-size-change=
"sizeChange('org', $event)"
/>
</TabPane>
<!-- 假种管理 -->
<TabPane
label=
"假种管理"
name=
"leaveType"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
类型名称:
</span>
<Input
v-model=
"filters.leaveType.type_name"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<Col
span=
"12"
>
<span>
类型编码:
</span>
<Input
v-model=
"filters.leaveType.type_code"
placeholder=
"请输入"
style=
"width: 70%"
/>
<Input
v-model=
"filters.leaveType.type_code"
placeholder=
"请输入"
style=
"width: 200px"
class=
"mr10"
/>
<span>
类型名称:
</span>
<Input
v-model=
"filters.leaveType.type_name"
placeholder=
"请输入"
style=
"width: 200px"
/>
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('leaveType')"
>
搜索
</Button>
...
...
@@ -52,13 +86,11 @@
<TabPane
label=
"办公用品分类管理"
name=
"materialCategory"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
分类名称:
</span>
<Input
v-model=
"filters.materialCategory.category_name"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<Col
span=
"12"
>
<span>
分类编码:
</span>
<Input
v-model=
"filters.materialCategory.category_code"
placeholder=
"请输入"
style=
"width: 70%"
/>
<Input
v-model=
"filters.materialCategory.category_code"
placeholder=
"请输入"
style=
"width: 200px"
class=
"mr10"
/>
<span>
分类名称:
</span>
<Input
v-model=
"filters.materialCategory.category_name"
placeholder=
"请输入"
style=
"width: 200px"
/>
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('materialCategory')"
>
搜索
</Button>
...
...
@@ -91,19 +123,15 @@
<TabPane
label=
"办公用品管理"
name=
"material"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
名称:
</span>
<Input
v-model=
"filters.material.material_name"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<span>
编码:
</span>
<Input
v-model=
"filters.material.material_code"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<Col
span=
"18"
>
<span>
分类:
</span>
<Select
v-model=
"filters.material.category_id"
clearable
style=
"width:
70%
"
>
<Select
v-model=
"filters.material.category_id"
clearable
style=
"width:
200px"
class=
"mr10
"
>
<Option
v-for=
"cat in materialCategoryOptions"
:key=
"cat.id"
:value=
"cat.id"
>
{{ cat.category_name }}
</Option>
</Select>
<span>
编码:
</span>
<Input
v-model=
"filters.material.material_code"
placeholder=
"请输入"
style=
"width: 200px"
class=
"mr10"
/>
<span>
名称:
</span>
<Input
v-model=
"filters.material.material_name"
placeholder=
"请输入"
style=
"width: 200px"
/>
</Col>
<Col
span=
"6"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('material')"
>
搜索
</Button>
...
...
@@ -180,27 +208,12 @@
<Input
type=
"textarea"
:rows=
"3"
v-model=
"modals.leaveType.form.remark"
placeholder=
"请输入类型描述"
/>
</FormItem>
<Row
:gutter=
"16"
>
<Col
span=
"12"
>
<FormItem
label=
"基准天数"
prop=
"base_days"
>
<InputNumber
v-model=
"modals.leaveType.form.base_days"
:min=
"0"
:precision=
"2"
style=
"width: 100%"
/>
</FormItem>
</Col>
<Col
span=
"12"
>
<!-- <Col span="12">
<FormItem label="年度上限" prop="max_days_per_year">
<InputNumber v-model="modals.leaveType.form.max_days_per_year" :min="0" :precision="2" style="width: 100%" />
</FormItem>
</Col>
</Row>
<Row
:gutter=
"16"
>
<Col
span=
"12"
>
<FormItem
label=
"需要审批"
>
<Select
v-model=
"modals.leaveType.form.need_approval"
style=
"width: 100%"
>
<Option
:value=
"1"
>
需要
</Option>
<Option
:value=
"0"
>
不需要
</Option>
</Select>
</FormItem>
</Col>
<Col
span=
"12"
>
</Col> -->
<Col
span=
"24"
>
<FormItem
label=
"排序号"
prop=
"order_no"
>
<InputNumber
v-model=
"modals.leaveType.form.order_no"
:min=
"0"
style=
"width: 100%"
/>
</FormItem>
...
...
@@ -356,9 +369,55 @@
</div>
</Modal>
<!-- 部门管理弹窗 -->
<Modal
v-model=
"modals.org.visible"
:title=
"modals.org.isEdit ? '修改部门' : '新增部门'"
width=
"600"
:mask-closable=
"false"
>
<Form
:label-width=
"120"
:model=
"modals.org.form"
:rules=
"modals.org.rules"
ref=
"orgForm"
>
<!-- <FormItem label="部门编码" prop="org_code">
<Input v-model="modals.org.form.org_code" placeholder="请输入部门编码" />
</FormItem> -->
<FormItem
label=
"部门名称"
prop=
"org_name"
>
<Input
v-model=
"modals.org.form.org_name"
placeholder=
"请输入部门名称"
/>
</FormItem>
<!-- <FormItem label="所属机构编码" prop="source_org">
<Input v-model="modals.org.form.source_org" placeholder="请输入所属机构编码" />
</FormItem> -->
<FormItem
label=
"部门描述"
prop=
"remark"
>
<Input
type=
"textarea"
:rows=
"3"
v-model=
"modals.org.form.remark"
placeholder=
"请输入部门描述"
/>
</FormItem>
<FormItem
label=
"排序号"
prop=
"order_no"
>
<InputNumber
v-model=
"modals.org.form.order_no"
:min=
"0"
style=
"width: 100%"
/>
</FormItem>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"modals.org.visible = false"
>
取消
</Button>
<Button
type=
"primary"
:loading=
"modals.org.saving"
@
click=
"handleSave('org')"
>
保存
</Button>
</div>
</Modal>
<!-- 人员划分弹窗 -->
<Modal
v-model=
"userAssignModal.visible"
title=
"人员划分"
width=
"800"
:mask-closable=
"false"
>
<div
style=
"margin-bottom: 16px;"
>
<span
style=
"font-weight: bold;"
>
部门:
</span>
{{ userAssignModal.orgName }}
</div>
<div
style=
"margin-bottom: 16px;"
>
<span
style=
"font-weight: bold;"
>
已划分人员:
</span>
<div
style=
"margin-top: 8px;"
>
<Tag
v-for=
"user in userAssignModal.selectedUsers"
:key=
"user.user_id"
closable
@
on-close=
"removeAssignedUser(user)"
>
{{ user.user_name }}
</Tag>
</div>
</div>
<div
slot=
"footer"
>
<Button
@
click=
"userAssignModal.visible = false"
>
取消
</Button>
<Button
type=
"primary"
@
click=
"addUsersToOrg"
>
添加人员
</Button>
<Button
type=
"primary"
:loading=
"userAssignModal.saving"
@
click=
"saveUserAssignment"
>
保存
</Button>
</div>
</Modal>
<!-- 人员选择器 -->
<UserMultiSelector
v-model=
"userSelectorVisible"
:round=
"userRound"
@
on-ok=
"handleUserSelectorOk"
@
cancel=
"userSelectorVisible = false"
/>
...
...
@@ -379,7 +438,11 @@ import {
importMaterial
,
getPermissionConfigList
,
savePermissionUsers
,
getUserDmPermissionList
getUserDmPermissionList
,
getOrgList
,
saveOrg
,
deleteOrg
,
assignUsersToOrg
}
from
'@/api/key-dm'
import
axios
from
'axios'
import
UserMultiSelector
from
'@/view/key-person/key_dm_user/userMultiSelector.vue'
...
...
@@ -393,25 +456,29 @@ export default {
filters
:
{
leaveType
:
{
type_name
:
''
,
type_code
:
''
},
materialCategory
:
{
category_name
:
''
,
category_code
:
''
},
material
:
{
material_name
:
''
,
material_code
:
''
,
category_id
:
''
}
material
:
{
material_name
:
''
,
material_code
:
''
,
category_id
:
''
},
org
:
{
org_name
:
''
,
org_code
:
''
}
},
tables
:
{
permissionConfig
:
[],
leaveType
:
[],
materialCategory
:
[],
material
:
[]
material
:
[],
org
:
[]
},
loading
:
{
permissionConfig
:
false
,
leaveType
:
false
,
materialCategory
:
false
,
material
:
false
material
:
false
,
org
:
false
},
pagers
:
{
permissionConfig
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
leaveType
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
materialCategory
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
material
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
}
material
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
org
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
}
},
modals
:
{
leaveType
:
{
...
...
@@ -473,6 +540,23 @@ export default {
category_id
:
[{
required
:
true
,
message
:
'请选择分类'
,
trigger
:
'change'
}],
material_name
:
[{
required
:
true
,
message
:
'请输入物料名称'
,
trigger
:
'blur'
}]
}
},
org
:
{
visible
:
false
,
isEdit
:
false
,
saving
:
false
,
form
:
{
id
:
''
,
source_org
:
''
,
org_code
:
''
,
org_name
:
''
,
remark
:
''
,
order_no
:
0
},
rules
:
{
// org_code: [{ required: true, message: '请输入部门编码', trigger: 'blur' }],
org_name
:
[{
required
:
true
,
message
:
'请输入部门名称'
,
trigger
:
'blur'
}]
}
}
},
userConfigModal
:
{
...
...
@@ -482,6 +566,13 @@ export default {
permissionName
:
''
,
selectedUsers
:
[]
},
userAssignModal
:
{
visible
:
false
,
saving
:
false
,
orgId
:
''
,
orgName
:
''
,
selectedUsers
:
[]
},
userSelectorVisible
:
false
,
importShow
:
false
,
impBtnDisabled
:
false
,
...
...
@@ -490,8 +581,8 @@ export default {
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'类型编码'
,
key
:
'type_code'
,
align
:
'center'
},
{
title
:
'类型名称'
,
key
:
'type_name'
,
align
:
'center'
},
{
title
:
'基准天数'
,
key
:
'base_days'
,
align
:
'center'
,
width
:
100
},
{
title
:
'需要审批'
,
key
:
'need_approval'
,
align
:
'center'
,
width
:
100
,
render
:
(
h
,
{
row
})
=>
h
(
'span'
,
row
.
need_approval
===
1
?
'需要'
:
'不需要'
)
},
//
{ title: '基准天数', key: 'base_days', align: 'center', width: 100 },
//
{ title: '需要审批', key: 'need_approval', align: 'center', width: 100, render: (h, { row }) => h('span', row.need_approval === 1 ? '需要' : '不需要') },
{
title
:
'排序号'
,
key
:
'order_no'
,
align
:
'center'
,
width
:
100
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
180
,
fixed
:
'right'
}
],
...
...
@@ -528,12 +619,23 @@ export default {
{
title
:
'配置人员'
,
key
:
'user_names'
,
align
:
'center'
,
minWidth
:
300
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
120
,
fixed
:
'right'
}
],
orgColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
// { title: '部门编码', key: 'org_code', align: 'center' },
{
title
:
'部门名称'
,
key
:
'org_name'
,
align
:
'center'
},
// { title: '所属机构编码', key: 'source_org', align: 'center' },
{
title
:
'部门人员'
,
key
:
'user_names'
,
align
:
'center'
},
{
title
:
'描述'
,
key
:
'remark'
,
align
:
'center'
},
{
title
:
'排序号'
,
key
:
'order_no'
,
align
:
'center'
,
width
:
100
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
200
,
fixed
:
'right'
}
],
power
:
{
leave_approval
:
false
,
// 请假审核
leave_view
:
false
,
// 请假查询(统计)
supply_approval
:
false
,
// 用品申领审核
supply_view
:
false
// 用品查询(统计)
}
},
userRound
:
'1'
}
},
created
()
{
...
...
@@ -572,7 +674,8 @@ export default {
permissionConfig
:
()
=>
Promise
.
resolve
({
data
:
{
errcode
:
0
,
data
:
[]
}
}),
leaveType
:
getLeaveTypeList
,
materialCategory
:
getMaterialCategoryList
,
material
:
getMaterialList
material
:
getMaterialList
,
org
:
getOrgList
}
const
api
=
apiMap
[
tab
]
if
(
!
api
)
return
...
...
@@ -597,7 +700,8 @@ export default {
permissionConfig
:
()
=>
({}),
leaveType
:
()
=>
({
type_name
:
''
,
type_code
:
''
}),
materialCategory
:
()
=>
({
category_name
:
''
,
category_code
:
''
}),
material
:
()
=>
({
material_name
:
''
,
material_code
:
''
,
category_id
:
''
})
material
:
()
=>
({
material_name
:
''
,
material_code
:
''
,
category_id
:
''
}),
org
:
()
=>
({
org_name
:
''
,
org_code
:
''
})
}
this
.
filters
[
tab
]
=
resetMap
[
tab
]()
this
.
pagers
[
tab
].
pageNo
=
1
...
...
@@ -662,6 +766,14 @@ export default {
can_borrow
:
1
,
material_desc
:
''
,
order_no
:
0
},
org
:
{
id
:
''
,
source_org
:
''
,
org_code
:
''
,
org_name
:
''
,
remark
:
''
,
order_no
:
0
}
}
return
JSON
.
parse
(
JSON
.
stringify
(
defaults
[
tab
]))
...
...
@@ -676,7 +788,8 @@ export default {
const
saveApiMap
=
{
leaveType
:
saveLeaveType
,
materialCategory
:
saveMaterialCategory
,
material
:
saveMaterial
material
:
saveMaterial
,
org
:
saveOrg
}
const
api
=
saveApiMap
[
tab
]
api
(
modal
.
form
).
then
(
ret
=>
{
...
...
@@ -698,7 +811,8 @@ export default {
const
deleteApiMap
=
{
leaveType
:
deleteLeaveType
,
materialCategory
:
deleteMaterialCategory
,
material
:
deleteMaterial
material
:
deleteMaterial
,
org
:
deleteOrg
}
const
api
=
deleteApiMap
[
tab
]
api
({
id
:
row
.
id
}).
then
(
ret
=>
{
...
...
@@ -748,17 +862,29 @@ export default {
console
.
log
(
'this.userConfigModal'
,
this
.
userConfigModal
)
},
addUsers
()
{
this
.
userRound
=
'1'
this
.
userSelectorVisible
=
true
},
handleUserSelectorOk
(
selectedUsers
)
{
// 将新选择的用户添加到已选用户列表中,避免重复
const
existingIds
=
this
.
userConfigModal
.
selectedUsers
.
map
(
u
=>
u
.
user_id
)
const
newUsers
=
selectedUsers
.
filter
(
u
=>
!
existingIds
.
includes
(
u
.
id
)).
map
(
u
=>
({
user_id
:
u
.
id
,
user_name
:
u
.
name
,
gh
:
u
.
gh
}))
this
.
userConfigModal
.
selectedUsers
=
[...
this
.
userConfigModal
.
selectedUsers
,
...
newUsers
]
if
(
this
.
userConfigModal
.
visible
)
{
// 权限配置弹窗
const
existingIds
=
this
.
userConfigModal
.
selectedUsers
.
map
(
u
=>
u
.
user_id
)
const
newUsers
=
selectedUsers
.
filter
(
u
=>
!
existingIds
.
includes
(
u
.
id
)).
map
(
u
=>
({
user_id
:
u
.
id
,
user_name
:
u
.
name
,
gh
:
u
.
gh
}))
this
.
userConfigModal
.
selectedUsers
=
[...
this
.
userConfigModal
.
selectedUsers
,
...
newUsers
]
}
else
if
(
this
.
userAssignModal
.
visible
)
{
// 人员划分弹窗
const
existingIds
=
this
.
userAssignModal
.
selectedUsers
.
map
(
u
=>
u
.
user_id
)
const
newUsers
=
selectedUsers
.
filter
(
u
=>
!
existingIds
.
includes
(
u
.
id
)).
map
(
u
=>
({
user_id
:
u
.
id
,
user_name
:
u
.
name
,
gh
:
u
.
gh
}))
this
.
userAssignModal
.
selectedUsers
=
[...
this
.
userAssignModal
.
selectedUsers
,
...
newUsers
]
}
this
.
userSelectorVisible
=
false
},
removeUser
(
user
)
{
...
...
@@ -876,6 +1002,46 @@ export default {
const
areaId
=
info
.
area_id
||
''
if
(
areaId
&&
areaId
.
startsWith
(
'2201'
))
return
true
return
false
},
openUserAssignModal
(
row
)
{
this
.
userAssignModal
.
visible
=
true
this
.
userAssignModal
.
orgId
=
row
.
id
this
.
userAssignModal
.
orgName
=
row
.
org_name
this
.
userAssignModal
.
selectedUsers
=
row
.
user_names
?
(
JSON
.
parse
(
row
.
users
)
||
[])
:
[]
// 加载该部门已分配的人员
// this.loadOrgAssignedUsers(row.id)
},
// loadOrgAssignedUsers (orgId) {
// getOrgList({ pageNo: 1, pageSize: 1000, params: { id: orgId } }).then(ret => {
// if (ret.data && ret.data.errcode === 0) {
// const data = ret.data.data || {}
// // 这里可以根据实际需求调整如何获取已分配的人员
// // 暂时设置为空,后续根据实际业务逻辑调整
// }
// })
// },
addUsersToOrg
()
{
this
.
userRound
=
'2'
this
.
userSelectorVisible
=
true
},
removeAssignedUser
(
user
)
{
this
.
userAssignModal
.
selectedUsers
=
this
.
userAssignModal
.
selectedUsers
.
filter
(
u
=>
u
.
user_id
!==
user
.
user_id
)
},
saveUserAssignment
()
{
this
.
userAssignModal
.
saving
=
true
const
userIds
=
this
.
userAssignModal
.
selectedUsers
.
map
(
u
=>
u
.
user_id
)
assignUsersToOrg
({
org_id
:
this
.
userAssignModal
.
orgId
,
user_ids
:
userIds
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
fetchList
(
"org"
)
this
.
$Message
.
success
(
'保存成功'
)
this
.
userAssignModal
.
visible
=
false
}
else
{
this
.
$Notice
.
error
({
title
:
'保存失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
finally
(()
=>
{
})
}
}
}
...
...
src/view/key-person/key_dm_inventory/stats.vue
View file @
7452feec
...
...
@@ -152,84 +152,128 @@ export default {
const
et
=
this
.
workEnd
?
normalizeVisitTimeValue
(
this
.
workEnd
)
:
null
if
(
type
===
'leave'
)
{
this
.
detailModal
.
columns
=
[
{
title
:
'人员'
,
key
:
'user_name'
,
align
:
'center'
},
{
title
:
'开始'
,
key
:
'start_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
start_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
{
title
:
'人员'
,
key
:
'user_name'
,
align
:
'center'
},
{
title
:
'开始'
,
key
:
'start_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
start_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
}
return
h
(
'span'
,
'-'
)
}
return
h
(
'span'
,
'-'
)
}},
{
title
:
'结束'
,
key
:
'end_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
end_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
},
{
title
:
'结束'
,
key
:
'end_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
end_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
}
return
h
(
'span'
,
'-'
)
}
return
h
(
'span'
,
'-'
)
}},
{
title
:
'时长'
,
key
:
'duration'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
status
=
params
.
row
.
status
let
statusText
=
''
switch
(
status
)
{
case
0
:
statusText
=
'未提交'
;
break
case
1
:
statusText
=
'审核中'
;
break
case
9
:
statusText
=
'审核通过'
;
break
case
-
1
:
statusText
=
'驳回'
;
break
default
:
statusText
=
status
},
{
title
:
'时长'
,
key
:
'duration'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'status'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
status
=
params
.
row
.
status
let
statusText
=
''
switch
(
status
)
{
case
0
:
statusText
=
'未提交'
;
break
case
1
:
statusText
=
'审核中'
;
break
case
9
:
statusText
=
'审核通过'
;
break
case
-
1
:
statusText
=
'驳回'
;
break
default
:
statusText
=
status
}
return
h
(
'span'
,
statusText
)
}
return
h
(
'span'
,
statusText
)
}}
}
]
getWorkloadDetails
({
user_id
:
row
.
user_id
,
start
:
st
,
end
:
et
,
type
:
'leave'
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
detailModal
.
rows
=
ret
.
data
.
data
||
[];
this
.
detailModal
.
visible
=
true
}
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
})
}
else
{
this
.
detailModal
.
columns
=
[
{
title
:
'申请时间'
,
key
:
'submit_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
submit_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
{
title
:
'申请时间'
,
key
:
'submit_time'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
time
=
params
.
row
.
submit_time
if
(
time
)
{
const
date
=
new
Date
(
time
)
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
seconds
=
String
(
date
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
h
(
'span'
,
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
)
}
return
h
(
'span'
,
'-'
)
}
return
h
(
'span'
,
'-'
)
}},
{
title
:
'物料'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
,
align
:
'center'
},
{
title
:
'归还数量'
,
key
:
'returned_quantity'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'approval_status'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
status
=
params
.
row
.
approval_status
let
statusText
=
''
switch
(
status
)
{
case
0
:
statusText
=
'待提交'
;
break
case
1
:
statusText
=
'审核中'
;
break
case
9
:
statusText
=
'审核通过'
;
break
case
-
1
:
statusText
=
'驳回'
;
break
default
:
statusText
=
status
},
{
title
:
'物料'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
,
align
:
'center'
},
{
title
:
'归还数量'
,
key
:
'returned_quantity'
,
align
:
'center'
},
{
title
:
'状态'
,
key
:
'approval_status'
,
align
:
'center'
,
render
:
(
h
,
params
)
=>
{
const
status
=
params
.
row
.
approval_status
let
statusText
=
''
switch
(
status
)
{
case
0
:
statusText
=
'待提交'
;
break
case
1
:
statusText
=
'审核中'
;
break
case
9
:
statusText
=
'审核通过'
;
break
case
-
1
:
statusText
=
'驳回'
;
break
default
:
statusText
=
status
}
return
h
(
'span'
,
statusText
)
}
return
h
(
'span'
,
statusText
)
}}
}
]
getWorkloadDetails
({
user_id
:
row
.
user_id
,
start
:
st
,
end
:
et
,
type
:
'inventory'
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
detailModal
.
rows
=
ret
.
data
.
data
||
[];
this
.
detailModal
.
visible
=
true
}
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
...
...
src/view/key-person/key_dm_leave/index.vue
View file @
7452feec
...
...
@@ -4,22 +4,20 @@
<TabPane
label=
"请假申请"
name=
"apply"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
class=
"mt8"
>
<Col
span=
"
12
"
>
<Col
span=
"
20
"
>
<span>
开始:
</span>
<DatePicker
v-model=
"filters.apply.start_time"
type=
"date"
placeholder=
"开始日期"
style=
"min-width:110px;margin-right:20px"
/>
<span>
结束:
</span>
<DatePicker
v-model=
"filters.apply.end_time"
type=
"date"
placeholder=
"结束日期"
style=
"min-width:110px;margin-right:20px"
/>
</Col>
<Col
span=
"8"
>
<span>
状态:
</span>
<Select
v-model=
"filters.apply.status"
style=
"width:
60%
"
>
<Select
v-model=
"filters.apply.status"
style=
"width:
150px
"
>
<Option
v-for=
"opt in statusOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{
opt
.
name
}}
</Option>
</Select>
</Col>
<Col
span=
"4"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('apply')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('apply')"
>
重置
</Button>
<Button
type=
"
success
"
@
click=
"openApplyModal"
>
申请
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleReset('apply')"
>
重置
</Button>
<Button
type=
"
primary
"
@
click=
"openApplyModal"
>
申请
</Button>
</Col>
</Row>
</div>
...
...
@@ -53,21 +51,19 @@
<TabPane
label=
"审核历史查询"
name=
"history"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
span=
"
12
"
>
<Col
span=
"
20
"
>
<span>
开始:
</span>
<DatePicker
v-model=
"filters.history.start_time"
type=
"date"
placeholder=
"开始日期"
style=
"min-width:110px;margin-right:20px"
/>
<span>
结束:
</span>
<DatePicker
v-model=
"filters.history.end_time"
type=
"date"
placeholder=
"结束日期"
style=
"min-width:110px;margin-right:20px"
/>
</Col>
<Col
span=
"8"
>
<span>
状态:
</span>
<Select
v-model=
"filters.history.status"
style=
"width:
60%
"
>
<Select
v-model=
"filters.history.status"
style=
"width:
150px"
class=
"mr10
"
>
<Option
v-for=
"opt in statusOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{ opt.name }}
</Option>
</Select>
</Col>
<Col
span=
"4"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('history')"
>
搜索
</Button>
<Button
@
click=
"handleReset('history')"
>
重置
</Button>
<Button
type=
"primary"
@
click=
"handleReset('history')"
>
重置
</Button>
</Col>
</Row>
</div>
...
...
@@ -83,21 +79,19 @@
<TabPane
label=
"请假申请查询"
name=
"query"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
span=
"
8
"
>
<Col
span=
"
16
"
>
<span>
开始:
</span>
<DatePicker
v-model=
"filters.query.start_time"
type=
"date"
placeholder=
"开始日期"
style=
"min-width:110px;margin-right:20px"
/>
<span>
结束:
</span>
<DatePicker
v-model=
"filters.query.end_time"
type=
"date"
placeholder=
"结束日期"
style=
"min-width:110px;margin-right:20px"
/>
</Col>
<Col
span=
"8"
>
<span>
状态:
</span>
<Select
v-model=
"filters.query.status"
style=
"width:
60%
"
>
<Select
v-model=
"filters.query.status"
style=
"width:
150px
"
>
<Option
v-for=
"opt in statusOptions"
:key=
"opt.id"
:value=
"opt.id"
>
{{ opt.name }}
</Option>
</Select>
</Col>
<Col
span=
"8"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('query')"
>
搜索
</Button>
<Button
@
click=
"handleReset('query')"
>
重置
</Button>
<Button
type=
"primary"
@
click=
"handleReset('query')"
>
重置
</Button>
</Col>
</Row>
</div>
...
...
@@ -119,11 +113,11 @@
<span>
结束:
</span>
<DatePicker
v-model=
"statsEnd"
type=
"date"
placeholder=
"结束日期"
style=
"min-width:110px;margin-right:20px"
/>
<span>
部门:
</span>
<Input
v-model=
"statsDept"
placeholder=
"请输入部门名称"
style=
"width:
65%
"
/>
<Input
v-model=
"statsDept"
placeholder=
"请输入部门名称"
style=
"width:
200px
"
/>
</Col>
<Col
span=
"8"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"loadStats"
>
统计
</Button>
<Button
@
click=
"resetStats"
>
重置
</Button>
<Button
type=
"primary"
@
click=
"resetStats"
>
重置
</Button>
</Col>
</Row>
</div>
...
...
@@ -415,6 +409,7 @@ export default {
if
(
name
===
'pending'
)
this
.
fetchList
(
'pending'
)
if
(
name
===
'history'
)
this
.
fetchList
(
'history'
)
if
(
name
===
'query'
)
this
.
fetchList
(
'query'
)
if
(
name
===
'stats'
)
this
.
loadStats
()
},
fetchList
(
tab
)
{
const
apiMap
=
{
apply
:
getLeaveListByUserId
,
pending
:
getPendingList
,
history
:
getApprovalHistory
,
query
:
getLeaveList
}
...
...
src/view/key-person/key_dm_user/index.vue
View file @
7452feec
...
...
@@ -10,11 +10,11 @@
</Col>
-->
<Col
:span=
"12"
class=
"text-left"
>
<span>
姓名:
</span>
<Input
v-model=
"filters.name"
placeholder=
"请输入姓名"
style=
"width:
40%
"
/>
<Input
v-model=
"filters.name"
placeholder=
"请输入姓名"
style=
"width:
200px
"
/>
</Col>
<Col
:span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch"
>
搜索
</Button>
<Button
@
click=
"handleReset"
class=
"mr10"
>
重置
</Button>
<Button
type=
"primary"
@
click=
"handleReset"
class=
"mr10"
>
重置
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSync"
>
同步
</Button>
</Col>
</Row>
...
...
@@ -56,10 +56,10 @@
<!--
角色已移除
-->
<!--
<
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
=
"直属领导"
>
<
Input
v
-
model
=
"editModal.form.leader_name"
readonly
placeholder
=
"点击选择直属领导"
@
click
.
native
=
"selectLeader"
style
=
"cursor: pointer"
/>
<
/FormItem
>
<
FormItem
label
=
"是否离职"
>
<
Select
v
-
model
=
"editModal.form.is_leave"
style
=
"width: 160px"
>
<
Option
:
value
=
"0"
>
未离职
<
/Option
>
...
...
@@ -72,16 +72,26 @@
<
Button
type
=
"primary"
:
loading
=
"editModal.saving"
@
click
=
"saveEdit"
>
保存
<
/Button
>
<
/div
>
<
/Modal
>
<!--
人员选择器
-->
<
UserSelector
v
-
model
=
"userSelectorVisible"
permission
=
""
@
on
-
ok
=
"handleLeaderSelected"
@
cancel
=
"userSelectorVisible = false"
/>
<!--
领导与归属部门选择已移除
-->
<
/div
>
<
/template
>
<
script
>
import
{
getDmUserList
,
syncDmUsersByOffice
,
saveDmUser
}
from
'@/api/key-dm-user'
import
UserSelector
from
'./userSelector.vue'
import
{
normalizeVisitTimeValue
}
from
'@/view/key-person/key_dm_conf/dates.js'
export
default
{
name
:
'key-dm-user-index'
,
components
:
{
}
,
components
:
{
UserSelector
}
,
data
()
{
return
{
officeCode
:
''
,
...
...
@@ -103,7 +113,8 @@ export default {
visible
:
false
,
saving
:
false
,
form
:
{
}
}
}
,
userSelectorVisible
:
false
// leader / office state 已移除
}
}
,
...
...
@@ -167,7 +178,7 @@ export default {
const
params
=
{
office_code
:
this
.
officeCode
}
this
.
$Modal
.
confirm
({
title
:
'确认同步'
,
content
:
'将同步本机构及下属机构的用户,已存在的记录会被更新
(不覆盖 null 值)
,是否继续?'
,
content
:
'将同步本机构及下属机构的用户,已存在的记录会被更新,是否继续?'
,
onOk
:
()
=>
{
this
.
loading
=
true
syncDmUsersByOffice
(
params
).
then
(
ret
=>
{
...
...
@@ -188,11 +199,20 @@ export default {
this
.
editModal
.
form
=
copy
this
.
editModal
.
visible
=
true
}
,
selectLeader
()
{
this
.
userSelectorVisible
=
true
}
,
handleLeaderSelected
(
user
)
{
this
.
editModal
.
form
.
leader
=
user
.
id
this
.
editModal
.
form
.
leader_name
=
user
.
name
this
.
userSelectorVisible
=
false
}
,
/* leader / office 相关方法已移除 */
saveEdit
()
{
this
.
$refs
.
editForm
.
validate
(
valid
=>
{
// no strict validation here, just save
this
.
editModal
.
saving
=
true
this
.
editModal
.
form
.
in_work_time
=
this
.
editModal
.
form
.
in_work_time
?
normalizeVisitTimeValue
(
this
.
editModal
.
form
.
in_work_time
)
:
null
saveDmUser
(
this
.
editModal
.
form
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'保存成功'
)
...
...
src/view/key-person/key_dm_user/userMultiSelector.vue
View file @
7452feec
...
...
@@ -4,7 +4,7 @@
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
:span=
"12"
>
<span>
姓名:
</span>
<Input
v-model=
"filters.name"
placeholder=
"请输入姓名"
@
on-enter=
"handleSearch
"
/>
<Input
v-model=
"filters.name"
placeholder=
"请输入姓名"
style=
"width: 200px
"
/>
</Col>
<Col
:span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch"
>
搜索
</Button>
...
...
@@ -37,7 +37,9 @@ export default {
name
:
'user-multi-selector'
,
props
:
{
// v-model: value 控制显示
value
:
{
type
:
Boolean
,
default
:
false
}
value
:
{
type
:
Boolean
,
default
:
false
},
// 范围参数1父,本级,下级2本级
round
:
{
type
:
String
,
default
:
'1'
}
},
data
()
{
return
{
...
...
@@ -50,12 +52,12 @@ export default {
confirming
:
false
,
columns
:
[
{
type
:
'selection'
,
width
:
60
,
align
:
'center'
},
{
title
:
'归属部门'
,
key
:
'office_name'
,
align
:
'center'
,
minWidth
:
150
},
{
title
:
'姓名'
,
key
:
'name'
,
align
:
'center'
,
minWidth
:
100
},
{
title
:
'工号'
,
key
:
'gh'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'邮箱'
,
key
:
'email'
,
align
:
'center'
,
minWidth
:
150
},
//
{ title: '邮箱', key: 'email', align: 'center', minWidth: 150 },
{
title
:
'电话'
,
key
:
'phone'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'手机'
,
key
:
'mobile'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'归属部门'
,
key
:
'office_name'
,
align
:
'center'
,
minWidth
:
150
}
{
title
:
'手机'
,
key
:
'mobile'
,
align
:
'center'
,
minWidth
:
120
}
]
}
},
...
...
@@ -78,11 +80,7 @@ export default {
methods
:
{
fetchList
()
{
this
.
loading
=
true
const
payload
=
{
pageNo
:
this
.
pager
.
pageNo
,
pageSize
:
this
.
pager
.
pageSize
,
params
:
this
.
filters
}
const
payload
=
Object
.
assign
({},
{
pageNo
:
this
.
pager
.
pageNo
,
pageSize
:
this
.
pager
.
pageSize
,
round
:
this
.
round
},
this
.
filters
)
getUserMultiSelectorList
(
payload
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
data
=
ret
.
data
.
data
||
{}
...
...
src/view/key-person/key_dm_user/userSelector.vue
0 → 100644
View file @
7452feec
<
template
>
<Modal
v-model=
"visible"
title=
"选择人员"
width=
"900"
:mask-closable=
"false"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
:span=
"12"
>
<span>
姓名:
</span>
<Input
v-model=
"filters.name"
placeholder=
"请输入姓名"
style=
"width: 200px"
/>
</Col>
<Col
:span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch"
>
搜索
</Button>
<Button
@
click=
"handleReset"
>
重置
</Button>
</Col>
</Row>
</div>
<Table
:data=
"rows"
:loading=
"loading"
:columns=
"columns"
border
highlight-row
@
on-current-change=
"onCurrentRowChange"
@
on-row-dblclick=
"onRowDblclick"
/>
<Page
class=
"page_style"
:total=
"pager.totalRecord"
:current=
"pager.pageNo"
:page-size=
"pager.pageSize"
show-total
show-sizer
@
on-change=
"pageChange"
@
on-page-size-change=
"sizeChange"
/>
<div
slot=
"footer"
>
<Button
@
click=
"handleCancel"
>
取消
</Button>
<Button
type=
"primary"
:loading=
"confirming"
@
click=
"handleConfirm"
:disabled=
"!selectedRow"
>
确定
</Button>
</div>
</Modal>
</
template
>
<
script
>
import
{
getUserSelectorList
}
from
'@/api/key-dm-user'
export
default
{
name
:
'user-selector'
,
props
:
{
// v-model: value 控制显示
value
:
{
type
:
Boolean
,
default
:
false
},
// 权限参数
permission
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
visibleInternal
:
false
,
filters
:
{
name
:
''
},
rows
:
[],
loading
:
false
,
pager
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
selectedRow
:
null
,
confirming
:
false
,
columns
:
[
{
title
:
'姓名'
,
key
:
'name'
,
align
:
'center'
,
minWidth
:
100
},
{
title
:
'工号'
,
key
:
'gh'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'邮箱'
,
key
:
'email'
,
align
:
'center'
,
minWidth
:
150
},
{
title
:
'电话'
,
key
:
'phone'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'手机'
,
key
:
'mobile'
,
align
:
'center'
,
minWidth
:
120
},
{
title
:
'归属部门'
,
key
:
'office_name'
,
align
:
'center'
,
minWidth
:
150
},
{
title
:
'人员分类'
,
key
:
'category_names'
,
align
:
'center'
,
minWidth
:
200
}
]
}
},
computed
:
{
visible
:
{
get
()
{
return
this
.
value
},
set
(
v
)
{
this
.
$emit
(
'input'
,
v
)
}
}
},
watch
:
{
visible
(
v
)
{
if
(
v
)
{
this
.
pager
.
pageNo
=
1
this
.
selectedRow
=
null
this
.
filters
.
name
=
''
this
.
fetchList
()
}
}
},
methods
:
{
fetchList
()
{
this
.
loading
=
true
const
payload
=
Object
.
assign
({},
{
pageNo
:
this
.
pager
.
pageNo
,
pageSize
:
this
.
pager
.
pageSize
,
office_code
:
this
.
officeCode
,
permission
:
this
.
permission
},
this
.
filters
)
getUserSelectorList
(
payload
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
data
=
ret
.
data
.
data
||
{}
this
.
rows
=
data
.
results
||
[]
this
.
pager
.
totalRecord
=
data
.
totalRecord
||
0
}
else
{
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
finally
(()
=>
{
this
.
loading
=
false
})
},
handleSearch
()
{
this
.
pager
.
pageNo
=
1
this
.
fetchList
()
},
handleReset
()
{
this
.
filters
=
{
name
:
''
}
this
.
pager
.
pageNo
=
1
this
.
fetchList
()
},
pageChange
(
pageNo
)
{
this
.
pager
.
pageNo
=
pageNo
this
.
fetchList
()
},
sizeChange
(
size
)
{
this
.
pager
.
pageSize
=
size
this
.
pager
.
pageNo
=
1
this
.
fetchList
()
},
onCurrentRowChange
(
currentRow
,
oldCurrentRow
)
{
this
.
selectedRow
=
currentRow
},
onRowDblclick
(
row
,
index
)
{
this
.
selectedRow
=
row
this
.
handleConfirm
()
},
handleCancel
()
{
this
.
$emit
(
'cancel'
)
this
.
$emit
(
'input'
,
false
)
},
handleConfirm
()
{
if
(
!
this
.
selectedRow
)
{
this
.
$Message
.
warning
(
'请先选择人员'
)
return
}
this
.
confirming
=
true
// emit selected user to parent
this
.
$emit
(
'on-ok'
,
this
.
selectedRow
)
this
.
$emit
(
'input'
,
false
)
this
.
confirming
=
false
}
}
}
</
script
>
<
style
scoped
>
.search-div
{
border
:
1px
solid
#dce1e7
;
padding
:
12px
;
margin-bottom
:
12px
;
background-color
:
#f8fbff
;
}
.mr10
{
margin-right
:
10px
;
}
.page_style
{
margin-top
:
12px
;
text-align
:
right
;
}
.text-right
{
text-align
:
right
;
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论