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
6391ed84
Commit
6391ed84
authored
Dec 25, 2025
by
yubin
Browse files
Options
Browse Files
Download
Plain Diff
请假
parents
de498718
3a9e709f
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
740 行增加
和
420 行删除
+740
-420
src/api/key-dm-stats.js
+0
-35
src/api/key-dm-user.js
+10
-3
src/api/key-dm.js
+64
-39
src/view/key-person/key_dm_conf/dates.js
+42
-0
src/view/key-person/key_dm_conf/index.vue
+202
-240
src/view/key-person/key_dm_conf/materialSelector.vue
+10
-11
src/view/key-person/key_dm_inventory/inbound.vue
+108
-24
src/view/key-person/key_dm_inventory/index.vue
+79
-26
src/view/key-person/key_dm_inventory/stats.vue
+70
-31
src/view/key-person/key_dm_leave/index.vue
+14
-11
src/view/key-person/key_dm_user/userMultiSelector.vue
+141
-0
没有找到文件。
src/api/key-dm-stats.js
deleted
100644 → 0
View file @
de498718
import
axios
from
'@/libs/api.request'
// 使用统计
export
const
getUsageStats
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectUsageStats'
,
method
:
'post'
,
data
:
param
})
}
export
const
getUsageDetails
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectUsageDetails'
,
method
:
'post'
,
data
:
param
})
}
// 工作量统计
export
const
getWorkloadStats
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadStats'
,
method
:
'post'
,
data
:
param
})
}
export
const
getWorkloadDetails
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadDetails'
,
method
:
'post'
,
data
:
param
})
}
src/api/key-dm-user.js
View file @
6391ed84
...
...
@@ -27,10 +27,10 @@ export const saveDmUser = (param) => {
})
}
//
分页查询日常人员可选上级领导列表
export
const
dmUserLeader
=
(
param
)
=>
{
//
获取人员选择器列表(根据机构和权限过滤)
export
const
getUserSelectorList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUser/
dmUserLeader
'
,
url
:
'/api/ac/jilinsscgsdp/keyDmUser/
selectUserSelectorList
'
,
method
:
'post'
,
data
:
param
})
...
...
@@ -48,6 +48,13 @@ export const dmUserOffice = (param) => {
export
const
getUserTypeList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
,
})
}
// 获取人员多选器列表(所有在职人员)
export
const
getUserMultiSelectorList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUser/selectUserMultiSelectorList'
,
method
:
'post'
,
data
:
param
})
...
...
src/api/key-dm.js
View file @
6391ed84
import
axios
from
'@/libs/api.request'
// ===== 人员
分类管理
=====
export
const
get
UserCategoryList
=
(
param
)
=>
{
// ===== 人员
权限配置
=====
export
const
get
PermissionConfigList
=
(
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
,
method
:
'post'
,
data
:
param
})
}
export
const
saveUserCategory
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/save'
,
method
:
'post'
,
data
:
param
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/selectPermissionConfigList'
,
method
:
'post'
})
}
export
const
deleteUserCategory
=
(
param
)
=>
{
export
const
savePermissionUsers
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/
delete
'
,
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/
savePermissionUsers
'
,
method
:
'post'
,
data
:
param
})
}
// =====
人员分类权限
管理 =====
export
const
get
UserCategoryPermission
List
=
(
param
)
=>
{
// =====
请假类型
管理 =====
export
const
get
LeaveType
List
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory
Permission/select
List'
,
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory
/selectLeaveType
List'
,
method
:
'post'
,
data
:
param
})
}
export
const
save
UserCategoryPermission
=
(
param
)
=>
{
export
const
save
LeaveType
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory
Permission/sav
e'
,
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory
/saveLeaveTyp
e'
,
method
:
'post'
,
data
:
param
})
}
// ===== 请假类型管理 =====
export
const
getLeaveTypeList
=
(
param
)
=>
{
export
const
deleteLeaveType
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
LeaveType/selectList
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/deleteLeaveType
'
,
method
:
'post'
,
data
:
param
})
}
export
const
saveLeaveType
=
(
param
)
=>
{
export
const
findLeaveTypeList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
LeaveType/save
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/findLeaveTypeList
'
,
method
:
'post'
,
data
:
param
})
}
export
const
deleteLeaveType
=
(
param
)
=>
{
// ===== 办公用品分类管理 =====
export
const
getMaterialCategoryList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
LeaveType/delete
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/selectMaterialCategoryList
'
,
method
:
'post'
,
data
:
param
})
}
// ===== 办公用品分类管理 =====
export
const
getMaterialCategoryList
=
(
param
)
=>
{
export
const
saveMaterialCategory
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
MaterialCategory/selectList
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/saveMaterialCategory
'
,
method
:
'post'
,
data
:
param
})
}
export
const
sav
eMaterialCategory
=
(
param
)
=>
{
export
const
delet
eMaterialCategory
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
MaterialCategory/save
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/deleteMaterialCategory
'
,
method
:
'post'
,
data
:
param
})
}
export
const
deleteMaterialCategory
=
(
param
)
=>
{
export
const
findMaterialCategoryList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
MaterialCategory/delete
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/findMaterialCategoryList
'
,
method
:
'post'
,
data
:
param
})
...
...
@@ -95,7 +85,7 @@ export const deleteMaterialCategory = (param) => {
// ===== 办公用品管理 =====
export
const
getMaterialList
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
Material/select
List'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/selectMaterial
List'
,
method
:
'post'
,
data
:
param
})
...
...
@@ -103,7 +93,7 @@ export const getMaterialList = (param) => {
export
const
saveMaterial
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
Material/save
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/saveMaterial
'
,
method
:
'post'
,
data
:
param
})
...
...
@@ -111,7 +101,7 @@ export const saveMaterial = (param) => {
export
const
deleteMaterial
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
Material/delete
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/deleteMaterial
'
,
method
:
'post'
,
data
:
param
})
...
...
@@ -120,7 +110,7 @@ export const deleteMaterial = (param) => {
// 导入物料(Excel)
export
const
importMaterial
=
(
formData
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDm
Material/import
'
,
url
:
'/api/ac/jilinsscgsdp/keyDm
UserCategory/importMaterial
'
,
method
:
'post'
,
data
:
formData
})
...
...
@@ -129,7 +119,42 @@ export const importMaterial = (formData) => {
// 下载物料导入模板
export
const
materialTemplateDownload
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmMaterial/templateDownload'
,
url
:
'/api/ac/jilinsscgsdp/keyDmUserCategory/templateDownload'
,
method
:
'post'
,
data
:
param
})
}
// --统计部分---------------------------------------------------------------------------------------------
// 使用统计
export
const
getUsageStats
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectUsageStats'
,
method
:
'post'
,
data
:
param
})
}
export
const
getUsageDetails
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectUsageDetails'
,
method
:
'post'
,
data
:
param
})
}
// 工作量统计
export
const
getWorkloadStats
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadStats'
,
method
:
'post'
,
data
:
param
})
}
export
const
getWorkloadDetails
=
(
param
)
=>
{
return
axios
.
request
({
url
:
'/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadDetails'
,
method
:
'post'
,
data
:
param
})
...
...
src/view/key-person/key_dm_conf/dates.js
0 → 100644
View file @
6391ed84
/* eslint-disable */
export
function
normalizeVisitTimeValue
(
value
)
{
if
(
!
value
&&
value
!==
0
)
return
''
if
(
value
instanceof
Date
)
{
return
Number
.
isNaN
(
value
.
getTime
())
?
''
:
formatDateSegments
(
value
)
}
if
(
typeof
value
===
'number'
&&
!
Number
.
isNaN
(
value
))
{
const
fromNumber
=
new
Date
(
value
)
return
Number
.
isNaN
(
fromNumber
.
getTime
())
?
''
:
formatDateSegments
(
fromNumber
)
}
if
(
typeof
value
===
'string'
)
{
const
trimmed
=
value
.
trim
()
if
(
!
trimmed
)
return
''
const
direct
=
new
Date
(
trimmed
)
if
(
!
Number
.
isNaN
(
direct
.
getTime
()))
return
formatDateSegments
(
direct
)
const
withSlash
=
new
Date
(
trimmed
.
replace
(
/-/g
,
'/'
))
if
(
!
Number
.
isNaN
(
withSlash
.
getTime
()))
return
formatDateSegments
(
withSlash
)
const
match
=
trimmed
.
match
(
/^
(\d{4})
-
(\d{2})
-
(\d{2})(?:[
T
](\d{2})
:
(\d{2})(?:
:
(\d{2}))?)?
$/
)
if
(
match
)
{
const
[,
y
,
m
,
d
,
hh
=
'00'
,
mm
=
'00'
,
ss
=
'00'
]
=
match
return
`
${
y
}
-
${
m
}
-
${
d
}
${
hh
}
:
${
mm
}
:
${
ss
}
`
}
return
''
}
if
(
value
&&
typeof
value
===
'object'
&&
typeof
value
.
valueOf
===
'function'
)
{
const
timestamp
=
value
.
valueOf
()
if
(
!
Number
.
isNaN
(
timestamp
))
{
const
fromValue
=
new
Date
(
timestamp
)
return
Number
.
isNaN
(
fromValue
.
getTime
())
?
''
:
formatDateSegments
(
fromValue
)
}
}
return
''
}
function
formatDateSegments
(
d
)
{
const
y
=
d
.
getFullYear
()
const
mm
=
String
(
d
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
dd
=
String
(
d
.
getDate
()).
padStart
(
2
,
'0'
)
const
HH
=
String
(
d
.
getHours
()).
padStart
(
2
,
'0'
)
const
MM
=
String
(
d
.
getMinutes
()).
padStart
(
2
,
'0'
)
const
SS
=
String
(
d
.
getSeconds
()).
padStart
(
2
,
'0'
)
return
`
${
y
}
-
${
mm
}
-
${
dd
}
${
HH
}
:
${
MM
}
:
${
SS
}
`
}
src/view/key-person/key_dm_conf/index.vue
View file @
6391ed84
<
template
>
<div
class=
"key-dm-wrapper"
>
<Tabs
v-model=
"activeTab"
@
on-click=
"handleTabChange"
>
<!-- 人员分类管理 -->
<TabPane
label=
"人员分类管理"
name=
"userCategory"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
分类名称:
</span>
<Input
v-model=
"filters.userCategory.catgory_name"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('userCategory')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('userCategory')"
>
重置
</Button>
<Button
type=
"success"
@
click=
"openAddModal('userCategory')"
>
新增
</Button>
</Col>
</Row>
</div>
<Table
border
:loading=
"loading.userCategory"
:columns=
"userCategoryColumns"
:data=
"tables.userCategory"
>
<!-- 人员权限配置 -->
<TabPane
label=
"人员权限配置"
name=
"permissionConfig"
>
<Table
border
:loading=
"loading.permissionConfig"
:columns=
"permissionConfigColumns"
:data=
"tables.permissionConfig"
>
<template
slot=
"action"
slot-scope=
"
{ row }">
<Button
size=
"small"
type=
"primary"
class=
"mr5"
@
click=
"openEditModal('userCategory', row)"
>
修改
</Button>
<Button
size=
"small"
type=
"warning"
class=
"mr5"
@
click=
"openPermissionModal(row)"
>
权限配置
</Button>
<Poptip
confirm
title=
"确认删除?"
transfer
@
on-ok=
"handleDelete('userCategory', row)"
>
<Button
size=
"small"
type=
"error"
>
删除
</Button>
</Poptip>
<Button
size=
"small"
type=
"primary"
@
click=
"openUserConfigModal(row)"
>
配置人员
</Button>
</
template
>
</Table>
<Page
class=
"page_style"
:total=
"pagers.userCategory.totalRecord"
:current=
"pagers.userCategory.pageNo"
:page-size=
"pagers.userCategory.pageSize"
show-total
show-sizer
@
on-change=
"pageChange('userCategory', $event)"
@
on-page-size-change=
"sizeChange('userCategory', $event)"
/>
</TabPane>
<!-- 假种管理 -->
<TabPane
label=
"假种管理"
name=
"leaveType"
>
<div
class=
"search-div"
>
...
...
@@ -51,8 +23,8 @@
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('leaveType')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('leaveType')"
>
重置
</Button>
<Button
type=
"
success
"
@
click=
"openAddModal('leaveType')"
>
新增
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleReset('leaveType')"
>
重置
</Button>
<Button
type=
"
primary
"
@
click=
"openAddModal('leaveType')"
>
新增
</Button>
</Col>
</Row>
</div>
...
...
@@ -82,16 +54,16 @@
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
分类名称:
</span>
<Input
v-model=
"filters.materialCategory.category_
N
ame"
placeholder=
"请输入"
style=
"width: 70%"
/>
<Input
v-model=
"filters.materialCategory.category_
n
ame"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<span>
分类编码:
</span>
<Input
v-model=
"filters.materialCategory.category_
C
ode"
placeholder=
"请输入"
style=
"width: 70%"
/>
<Input
v-model=
"filters.materialCategory.category_
c
ode"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"12"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('materialCategory')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('materialCategory')"
>
重置
</Button>
<Button
type=
"
success
"
@
click=
"openAddModal('materialCategory')"
>
新增
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleReset('materialCategory')"
>
重置
</Button>
<Button
type=
"
primary
"
@
click=
"openAddModal('materialCategory')"
>
新增
</Button>
</Col>
</Row>
</div>
...
...
@@ -120,23 +92,23 @@
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
<Col
span=
"6"
>
<span>
物料
名称:
</span>
<span>
名称:
</span>
<Input
v-model=
"filters.material.material_name"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<span>
物料
编码:
</span>
<span>
编码:
</span>
<Input
v-model=
"filters.material.material_code"
placeholder=
"请输入"
style=
"width: 70%"
/>
</Col>
<Col
span=
"6"
>
<span>
分类:
</span>
<Select
v-model=
"filters.material.category_id"
clearable
style=
"width: 70%"
>
<Option
v-for=
"cat in materialCategoryOptions"
:key=
"cat.id"
:value=
"cat.id"
>
{{ cat.category_
N
ame }}
</Option>
<Option
v-for=
"cat in materialCategoryOptions"
:key=
"cat.id"
:value=
"cat.id"
>
{{ cat.category_
n
ame }}
</Option>
</Select>
</Col>
<Col
span=
"6"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleSearch('material')"
>
搜索
</Button>
<Button
class=
"mr10"
@
click=
"handleReset('material')"
>
重置
</Button>
<Button
type=
"
success
"
@
click=
"openAddModal('material')"
>
新增
</Button>
<Button
type=
"primary"
class=
"mr10"
@
click=
"handleReset('material')"
>
重置
</Button>
<Button
type=
"
primary"
class=
"mr10
"
@
click=
"openAddModal('material')"
>
新增
</Button>
<Button
type=
"primary"
class=
"mr10"
v-if=
"showImport()"
@
click=
"importShow = true"
>
导入
</Button>
</Col>
</Row>
...
...
@@ -162,30 +134,13 @@
</TabPane>
</Tabs>
<!-- 人员分类管理弹窗 -->
<Modal
v-model=
"modals.userCategory.visible"
:title=
"modals.userCategory.isEdit ? '修改人员分类' : '新增人员分类'"
width=
"600"
:mask-closable=
"false"
>
<Form
:label-width=
"120"
:model=
"modals.userCategory.form"
:rules=
"modals.userCategory.rules"
ref=
"userCategoryForm"
>
<FormItem
label=
"分类名称"
prop=
"catgory_name"
>
<Input
v-model=
"modals.userCategory.form.catgory_name"
placeholder=
"请输入分类名称"
/>
</FormItem>
<FormItem
label=
"描述"
prop=
"remark"
>
<Input
type=
"textarea"
:rows=
"3"
v-model=
"modals.userCategory.form.remark"
placeholder=
"请输入描述"
/>
</FormItem>
<FormItem
label=
"排序号"
prop=
"order_no"
>
<InputNumber
v-model=
"modals.userCategory.form.order_no"
:min=
"0"
style=
"width: 100%"
/>
</FormItem>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"modals.userCategory.visible = false"
>
取消
</Button>
<Button
type=
"primary"
:loading=
"modals.userCategory.saving"
@
click=
"handleSave('userCategory')"
>
保存
</Button>
</div>
</Modal>
<!-- 导入物料弹窗 -->
<Modal
v-model=
"importShow"
title=
"物料导入"
width=
"360"
>
<Row
type=
"flex"
justify=
"center"
align=
"middle"
>
<Col
span=
"10"
>
<div
style=
"text-align: center;"
>
<Upload
action=
"#"
:show-upload-list=
"false"
:before-upload=
"handleBeforeUpload"
:format=
"['xls','xlsx']"
...
...
@@ -261,11 +216,11 @@
<!-- 办公用品分类管理弹窗 -->
<Modal
v-model=
"modals.materialCategory.visible"
:title=
"modals.materialCategory.isEdit ? '修改办公用品分类' : '新增办公用品分类'"
width=
"600"
:mask-closable=
"false"
>
<Form
:label-width=
"120"
:model=
"modals.materialCategory.form"
:rules=
"modals.materialCategory.rules"
ref=
"materialCategoryForm"
>
<FormItem
label=
"分类编码"
prop=
"category_
C
ode"
>
<Input
v-model=
"modals.materialCategory.form.category_
C
ode"
placeholder=
"请输入分类编码"
/>
<FormItem
label=
"分类编码"
prop=
"category_
c
ode"
>
<Input
v-model=
"modals.materialCategory.form.category_
c
ode"
placeholder=
"请输入分类编码"
/>
</FormItem>
<FormItem
label=
"分类名称"
prop=
"category_
N
ame"
>
<Input
v-model=
"modals.materialCategory.form.category_
N
ame"
placeholder=
"请输入分类名称"
/>
<FormItem
label=
"分类名称"
prop=
"category_
n
ame"
>
<Input
v-model=
"modals.materialCategory.form.category_
n
ame"
placeholder=
"请输入分类名称"
/>
</FormItem>
<FormItem
label=
"分类描述"
prop=
"remark"
>
<Input
type=
"textarea"
:rows=
"3"
v-model=
"modals.materialCategory.form.remark"
placeholder=
"请输入分类描述"
/>
...
...
@@ -287,20 +242,20 @@
<Col
span=
"12"
>
<FormItem
label=
"分类"
prop=
"category_id"
>
<Select
v-model=
"modals.material.form.category_id"
placeholder=
"请选择分类"
style=
"width: 100%"
>
<Option
v-for=
"cat in materialCategoryOptions"
:key=
"cat.id"
:value=
"cat.id"
>
{{ cat.category_
N
ame }}
</Option>
<Option
v-for=
"cat in materialCategoryOptions"
:key=
"cat.id"
:value=
"cat.id"
>
{{ cat.category_
n
ame }}
</Option>
</Select>
</FormItem>
</Col>
<Col
span=
"12"
>
<FormItem
label=
"
物料
编码"
prop=
"material_code"
>
<Input
v-model=
"modals.material.form.material_code"
placeholder=
"请输入
物料
编码"
/>
<FormItem
label=
"编码"
prop=
"material_code"
>
<Input
v-model=
"modals.material.form.material_code"
placeholder=
"请输入编码"
/>
</FormItem>
</Col>
</Row>
<Row
:gutter=
"16"
>
<Col
span=
"12"
>
<FormItem
label=
"
物料
名称"
prop=
"material_name"
>
<Input
v-model=
"modals.material.form.material_name"
placeholder=
"请输入
物料
名称"
/>
<FormItem
label=
"名称"
prop=
"material_name"
>
<Input
v-model=
"modals.material.form.material_name"
placeholder=
"请输入名称"
/>
</FormItem>
</Col>
<Col
span=
"12"
>
...
...
@@ -328,7 +283,7 @@
</FormItem>
</Col>
<Col
span=
"12"
>
<FormItem
label=
"
物料
状态"
prop=
"status"
>
<FormItem
label=
"状态"
prop=
"status"
>
<Select
v-model=
"modals.material.form.status"
style=
"width: 100%"
>
<Option
:value=
"0"
>
报废
</Option>
<Option
:value=
"1"
>
使用
</Option>
...
...
@@ -364,6 +319,13 @@
</FormItem>
</Col>
</Row>
<Row
:gutter=
"16"
>
<Col
span=
"24"
>
<FormItem
label=
"供应商"
prop=
"supplier_name"
>
<Input
v-model=
"modals.material.form.supplier_name"
placeholder=
"请输入供应商"
style=
"width: 100%"
/>
</FormItem>
</Col>
</Row>
<FormItem
label=
"物料描述"
prop=
"material_desc"
>
<Input
type=
"textarea"
:rows=
"3"
v-model=
"modals.material.form.material_desc"
placeholder=
"请输入物料描述"
/>
</FormItem>
...
...
@@ -374,31 +336,37 @@
</div>
</Modal>
<!-- 权限配置弹窗 -->
<Modal
v-model=
"permissionModal.visible"
title=
"权限配置"
width=
"600"
:mask-closable=
"false"
>
<Form
:label-width=
"120"
>
<FormItem
label=
"分类名称"
>
<Input
:value=
"permissionModal.categoryName"
disabled
/>
</FormItem>
<FormItem
label=
"权限配置"
>
<Select
v-model=
"permissionModal.selectedPermissions"
multiple
clearable
filterable
placeholder=
"请选择权限"
>
<Option
v-for=
"opt in permissionOptions"
:key=
"opt.value"
:value=
"opt.value"
>
{{ opt.label }}
</Option>
</Select>
</FormItem>
</Form>
<!-- 人员权限配置弹窗 -->
<Modal
v-model=
"userConfigModal.visible"
title=
"人员权限配置"
width=
"800"
:mask-closable=
"false"
>
<div
style=
"margin-bottom: 16px;"
>
<span
style=
"font-weight: bold;"
>
权限:
</span>
{{ userConfigModal.permissionName }}
</div>
<div
style=
"margin-bottom: 16px;"
>
<span
style=
"font-weight: bold;"
>
已配置人员:
</span>
<div
style=
"margin-top: 8px;"
>
<Tag
v-for=
"user in userConfigModal.selectedUsers"
:key=
"user.user_id"
closable
@
on-close=
"removeUser(user)"
>
{{ user.user_name }}
</Tag>
</div>
</div>
<div
slot=
"footer"
>
<Button
@
click=
"permissionModal.visible = false"
>
取消
</Button>
<Button
type=
"primary"
:loading=
"permissionModal.saving"
@
click=
"savePermission"
>
保存
</Button>
<Button
@
click=
"userConfigModal.visible = false"
>
取消
</Button>
<Button
type=
"primary"
@
click=
"addUsers"
>
添加人员
</Button>
<Button
type=
"primary"
:loading=
"userConfigModal.saving"
@
click=
"saveUserConfig"
>
保存
</Button>
</div>
</Modal>
<!-- 人员选择器 -->
<UserMultiSelector
v-model=
"userSelectorVisible"
@
on-ok=
"handleUserSelectorOk"
@
cancel=
"userSelectorVisible = false"
/>
</div>
</template>
<
script
>
import
{
getUserCategoryList
,
saveUserCategory
,
deleteUserCategory
,
getLeaveTypeList
,
saveLeaveType
,
deleteLeaveType
,
...
...
@@ -408,57 +376,43 @@ import {
getMaterialList
,
saveMaterial
,
deleteMaterial
,
getUserCategoryPermissionList
,
saveUserCategoryPermission
,
importMaterial
,
materialTemplateDownload
getPermissionConfigList
,
savePermissionUsers
}
from
'@/api/key-dm'
import
{
getDictList
}
from
'@/api/common'
import
axios
from
'axios'
import
UserMultiSelector
from
'@/view/key-person/key_dm_user/userMultiSelector.vue'
export
default
{
name
:
'key-dm-index'
,
components
:
{
UserMultiSelector
},
data
()
{
return
{
activeTab
:
'
userCategory
'
,
activeTab
:
'
permissionConfig
'
,
filters
:
{
userCategory
:
{
catgory_name
:
''
},
leaveType
:
{
type_name
:
''
,
type_code
:
''
},
materialCategory
:
{
category_
Name
:
''
,
category_C
ode
:
''
},
materialCategory
:
{
category_
name
:
''
,
category_c
ode
:
''
},
material
:
{
material_name
:
''
,
material_code
:
''
,
category_id
:
''
}
},
tables
:
{
userCategory
:
[],
permissionConfig
:
[],
leaveType
:
[],
materialCategory
:
[],
material
:
[]
},
loading
:
{
userCategory
:
false
,
permissionConfig
:
false
,
leaveType
:
false
,
materialCategory
:
false
,
material
:
false
},
pagers
:
{
userCategory
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
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
}
},
modals
:
{
userCategory
:
{
visible
:
false
,
isEdit
:
false
,
saving
:
false
,
form
:
{
id
:
''
,
catgory_name
:
''
,
remark
:
''
,
order_no
:
0
},
rules
:
{
catgory_name
:
[{
required
:
true
,
message
:
'请输入分类名称'
,
trigger
:
'blur'
}]
}
},
leaveType
:
{
visible
:
false
,
isEdit
:
false
,
...
...
@@ -484,14 +438,14 @@ export default {
saving
:
false
,
form
:
{
id
:
''
,
category_
C
ode
:
''
,
category_
N
ame
:
''
,
category_
c
ode
:
''
,
category_
n
ame
:
''
,
remark
:
''
,
order_no
:
0
},
rules
:
{
category_
C
ode
:
[{
required
:
true
,
message
:
'请输入分类编码'
,
trigger
:
'blur'
}],
category_
N
ame
:
[{
required
:
true
,
message
:
'请输入分类名称'
,
trigger
:
'blur'
}]
category_
c
ode
:
[{
required
:
true
,
message
:
'请输入分类编码'
,
trigger
:
'blur'
}],
category_
n
ame
:
[{
required
:
true
,
message
:
'请输入分类名称'
,
trigger
:
'blur'
}]
}
},
material
:
{
...
...
@@ -520,25 +474,17 @@ export default {
}
}
},
permission
Modal
:
{
userConfig
Modal
:
{
visible
:
false
,
saving
:
false
,
categoryId
:
''
,
category
Name
:
''
,
selected
Permission
s
:
[]
permissionCode
:
''
,
permission
Name
:
''
,
selected
User
s
:
[]
},
userSelectorVisible
:
false
,
importShow
:
false
,
impBtnDisabled
:
false
,
permissionOptions
:
[],
materialCategoryOptions
:
[],
userCategoryColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'分类名称'
,
key
:
'catgory_name'
,
align
:
'center'
},
{
title
:
'描述'
,
key
:
'remark'
,
align
:
'center'
},
{
title
:
'权限'
,
key
:
'permission_names'
,
align
:
'center'
,
minWidth
:
200
},
{
title
:
'排序号'
,
key
:
'order_no'
,
align
:
'center'
,
width
:
100
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
250
,
fixed
:
'right'
}
],
leaveTypeColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'类型编码'
,
key
:
'type_code'
,
align
:
'center'
},
...
...
@@ -550,20 +496,21 @@ export default {
],
materialCategoryColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'分类编码'
,
key
:
'category_
C
ode'
,
align
:
'center'
},
{
title
:
'分类名称'
,
key
:
'category_
N
ame'
,
align
:
'center'
},
{
title
:
'分类编码'
,
key
:
'category_
c
ode'
,
align
:
'center'
},
{
title
:
'分类名称'
,
key
:
'category_
n
ame'
,
align
:
'center'
},
{
title
:
'分类描述'
,
key
:
'remark'
,
align
:
'center'
},
{
title
:
'排序号'
,
key
:
'order_no'
,
align
:
'center'
,
width
:
100
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
180
,
fixed
:
'right'
}
],
materialColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'分类'
,
key
:
'category_name'
,
align
:
'center'
},
{
title
:
'物料编码'
,
key
:
'material_code'
,
align
:
'center'
},
{
title
:
'物料名称'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'规格型号'
,
key
:
'material_spec'
,
align
:
'center'
},
{
title
:
'单位'
,
key
:
'unit'
,
align
:
'center'
,
width
:
80
},
{
title
:
'单价'
,
key
:
'unit_price'
,
align
:
'center'
,
width
:
100
},
{
title
:
'分类'
,
key
:
'category_name'
,
minwidth
:
120
,
align
:
'center'
},
{
title
:
'物料编码'
,
key
:
'material_code'
,
minwidth
:
120
,
align
:
'center'
},
{
title
:
'物料名称'
,
key
:
'material_name'
,
minwidth
:
180
,
align
:
'center'
},
{
title
:
'规格型号'
,
key
:
'material_spec'
,
minwidth
:
100
,
align
:
'center'
},
{
title
:
'单位'
,
key
:
'unit'
,
align
:
'center'
,
minwidth
:
80
},
{
title
:
'单价'
,
key
:
'unit_price'
,
align
:
'center'
,
minwidth
:
100
},
{
title
:
'供应商'
,
key
:
'supplier_name'
,
align
:
'center'
,
minwidth
:
120
},
{
title
:
'物料状态'
,
key
:
'status'
,
align
:
'center'
,
...
...
@@ -573,22 +520,32 @@ export default {
return
h
(
'span'
,
statusMap
[
row
.
status
]
||
'-'
)
}
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
180
,
fixed
:
'right'
}
],
permissionConfigColumns
:
[
{
type
:
'index'
,
title
:
'序号'
,
width
:
60
,
align
:
'center'
},
{
title
:
'权限名称'
,
key
:
'permission_name'
,
align
:
'center'
,
minWidth
:
150
},
{
title
:
'配置人员'
,
key
:
'user_names'
,
align
:
'center'
,
minWidth
:
300
},
{
title
:
'操作'
,
slot
:
'action'
,
align
:
'center'
,
width
:
120
,
fixed
:
'right'
}
]
}
},
created
()
{
this
.
loadPermissionDict
()
this
.
loadMaterialCategoryOptions
()
this
.
loadPermissionConfig
()
this
.
fetchList
(
this
.
activeTab
)
},
methods
:
{
handleTabChange
(
name
)
{
this
.
activeTab
=
name
this
.
fetchList
(
name
)
if
(
name
===
'permissionConfig'
)
{
this
.
loadPermissionConfig
()
}
else
{
this
.
fetchList
(
name
)
}
},
fetchList
(
tab
)
{
const
apiMap
=
{
userCategory
:
getUserCategoryList
,
permissionConfig
:
()
=>
Promise
.
resolve
({
data
:
{
errcode
:
0
,
data
:
[]
}
})
,
leaveType
:
getLeaveTypeList
,
materialCategory
:
getMaterialCategoryList
,
material
:
getMaterialList
...
...
@@ -601,27 +558,6 @@ export default {
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
data
=
ret
.
data
.
data
||
{}
this
.
tables
[
tab
]
=
data
.
results
||
[]
// 如果是人员分类,加载每行的权限名称并拼接显示
if
(
tab
===
'userCategory'
&&
Array
.
isArray
(
this
.
tables
[
tab
])
&&
this
.
tables
[
tab
].
length
>
0
)
{
const
rows
=
this
.
tables
[
tab
]
// 并行查询每个分类的权限配置(可优化为批量接口)
const
promises
=
rows
.
map
(
r
=>
{
return
getUserCategoryPermissionList
({
category_id
:
r
.
id
}).
then
(
res
=>
{
let
names
=
''
if
(
res
.
data
&&
res
.
data
.
errcode
===
0
)
{
const
list
=
res
.
data
.
data
||
res
.
data
.
results
||
[]
names
=
(
Array
.
isArray
(
list
)
?
list
.
map
(
it
=>
it
.
permission_name
).
filter
(
Boolean
)
:
[]).
join
(
','
)
}
// 确保响应式设置字段
this
.
$set
(
r
,
'permission_names'
,
names
)
return
r
}).
catch
(()
=>
{
this
.
$set
(
r
,
'permission_names'
,
''
)
return
r
})
})
Promise
.
all
(
promises
).
then
(()
=>
{
/* table updated */
})
}
this
.
pagers
[
tab
].
totalRecord
=
data
.
totalRecord
||
0
}
else
{
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
.
errmsg
||
'请稍后重试'
})
...
...
@@ -634,9 +570,9 @@ export default {
},
handleReset
(
tab
)
{
const
resetMap
=
{
userCategory
:
()
=>
({
catgory_name
:
''
}),
permissionConfig
:
()
=>
({
}),
leaveType
:
()
=>
({
type_name
:
''
,
type_code
:
''
}),
materialCategory
:
()
=>
({
category_
Name
:
''
,
category_C
ode
:
''
}),
materialCategory
:
()
=>
({
category_
name
:
''
,
category_c
ode
:
''
}),
material
:
()
=>
({
material_name
:
''
,
material_code
:
''
,
category_id
:
''
})
}
this
.
filters
[
tab
]
=
resetMap
[
tab
]()
...
...
@@ -670,12 +606,6 @@ export default {
},
getDefaultForm
(
tab
)
{
const
defaults
=
{
userCategory
:
{
id
:
''
,
catgory_name
:
''
,
remark
:
''
,
order_no
:
0
},
leaveType
:
{
id
:
''
,
type_code
:
''
,
...
...
@@ -688,8 +618,8 @@ export default {
},
materialCategory
:
{
id
:
''
,
category_
C
ode
:
''
,
category_
N
ame
:
''
,
category_
c
ode
:
''
,
category_
n
ame
:
''
,
remark
:
''
,
order_no
:
0
},
...
...
@@ -720,7 +650,6 @@ export default {
if
(
!
valid
)
return
modal
.
saving
=
true
const
saveApiMap
=
{
userCategory
:
saveUserCategory
,
leaveType
:
saveLeaveType
,
materialCategory
:
saveMaterialCategory
,
material
:
saveMaterial
...
...
@@ -731,6 +660,10 @@ export default {
this
.
$Message
.
success
(
'保存成功'
)
modal
.
visible
=
false
this
.
fetchList
(
tab
)
// 如果是办公用品分类管理操作成功,刷新分类选项
if
(
tab
===
'materialCategory'
)
{
this
.
loadMaterialCategoryOptions
()
}
}
else
{
this
.
$Notice
.
error
({
title
:
'保存失败'
,
desc
:
ret
.
data
.
errmsg
||
'请稍后重试'
})
}
...
...
@@ -739,7 +672,6 @@ export default {
},
handleDelete
(
tab
,
row
)
{
const
deleteApiMap
=
{
userCategory
:
deleteUserCategory
,
leaveType
:
deleteLeaveType
,
materialCategory
:
deleteMaterialCategory
,
material
:
deleteMaterial
...
...
@@ -749,64 +681,15 @@ export default {
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'删除成功'
)
this
.
fetchList
(
tab
)
// 如果是办公用品分类管理删除成功,刷新分类选项
if
(
tab
===
'materialCategory'
)
{
this
.
loadMaterialCategoryOptions
()
}
}
else
{
this
.
$Notice
.
error
({
title
:
'删除失败'
,
desc
:
ret
.
data
.
errmsg
||
'请稍后重试'
})
}
})
},
openPermissionModal
(
row
)
{
this
.
permissionModal
.
visible
=
true
this
.
permissionModal
.
categoryId
=
row
.
id
this
.
permissionModal
.
categoryName
=
row
.
catgory_name
this
.
permissionModal
.
selectedPermissions
=
[]
// 加载已有权限
getUserCategoryPermissionList
({
category_id
:
row
.
id
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
const
list
=
ret
.
data
.
data
||
ret
.
data
.
results
||
[]
this
.
permissionModal
.
selectedPermissions
=
list
.
map
(
item
=>
item
.
permission_mark
).
filter
(
Boolean
)
}
})
},
savePermission
()
{
if
(
!
this
.
permissionModal
.
categoryId
)
{
this
.
$Message
.
warning
(
'分类ID不存在'
)
return
}
this
.
permissionModal
.
saving
=
true
const
permissions
=
Array
.
isArray
(
this
.
permissionModal
.
selectedPermissions
)
?
this
.
permissionModal
.
selectedPermissions
:
[]
const
permissionList
=
permissions
.
map
(
mark
=>
{
const
opt
=
this
.
permissionOptions
.
find
(
p
=>
p
.
value
===
mark
)
return
{
category_id
:
this
.
permissionModal
.
categoryId
,
permission_mark
:
mark
,
permission_name
:
opt
?
opt
.
label
:
mark
}
})
saveUserCategoryPermission
({
category_id
:
this
.
permissionModal
.
categoryId
,
permissions
:
permissionList
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'保存成功'
)
this
.
permissionModal
.
visible
=
false
this
.
fetchList
(
'userCategory'
)
}
else
{
this
.
$Notice
.
error
({
title
:
'保存失败'
,
desc
:
ret
.
data
.
errmsg
||
'请稍后重试'
})
}
}).
finally
(()
=>
{
this
.
permissionModal
.
saving
=
false
})
},
loadPermissionDict
()
{
// 从字典获取权限选项,字典类型为 daily_manage_dict_permission
getDictList
({
type
:
'daily_manage_dict_permission'
}).
then
(
res
=>
{
if
(
res
.
data
&&
res
.
data
.
errcode
===
0
)
{
const
results
=
res
.
data
.
data
&&
res
.
data
.
data
.
results
?
res
.
data
.
data
.
results
:
[]
this
.
permissionOptions
=
results
.
map
(
it
=>
({
label
:
it
.
label
||
it
.
name
||
''
,
value
:
it
.
value
||
it
.
dictValue
||
''
})).
filter
(
it
=>
it
.
label
&&
it
.
value
)
}
})
},
loadMaterialCategoryOptions
()
{
getMaterialCategoryList
({
pageNo
:
1
,
pageSize
:
1000
,
params
:
{}
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
...
...
@@ -816,26 +699,104 @@ export default {
const
raw
=
data
.
results
||
[]
// 规范化后端字段名,确保 id 字段为小写 id,以便 Select v-model 绑定正常工作
this
.
materialCategoryOptions
=
Array
.
isArray
(
raw
)
?
raw
.
map
(
it
=>
({
id
:
(
it
.
Id
||
it
.
id
||
it
.
category_C
ode
||
''
).
toString
(),
category_
Name
:
(
it
.
category_Name
||
it
.
categoryName
||
it
.
category_C
ode
||
''
)
id
:
(
it
.
id
||
it
.
id
||
it
.
category_c
ode
||
''
).
toString
(),
category_
name
:
(
it
.
category_name
||
it
.
categoryName
||
it
.
category_c
ode
||
''
)
}))
:
[]
}
})
},
tplDownload
()
{
// 下载物料导入模板
materialTemplateDownload
({}).
then
(
ret
=>
{
if
(
ret
&&
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
// const data = ret.data.data
// 如果后端直接返回文件流需要采用 axios blob 下载,这里假设返回 url 或 blob handled by backend
// 简单提示或可实现下载逻辑
this
.
$Notice
.
success
({
title
:
'模板已准备,请在后台下载'
})
loadPermissionConfig
()
{
// 从字典获取权限配置数据,并加载对应的用户配置
this
.
loading
.
permissionConfig
=
true
getPermissionConfigList
().
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
tables
.
permissionConfig
=
ret
.
data
.
data
||
[]
}
else
{
this
.
$Notice
.
error
({
title
:
'
模板下
载失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
this
.
$Notice
.
error
({
title
:
'
加
载失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
catch
(()
=>
{
this
.
$Notice
.
error
({
title
:
'模板下载失败'
})
})
}).
finally
(()
=>
{
this
.
loading
.
permissionConfig
=
false
})
},
openUserConfigModal
(
row
)
{
this
.
userConfigModal
.
visible
=
true
this
.
userConfigModal
.
permissionCode
=
row
.
permission_code
this
.
userConfigModal
.
permissionName
=
row
.
permission_name
this
.
userConfigModal
.
selectedUsers
=
row
.
user_names
?
(
JSON
.
parse
(
row
.
users
)
||
[])
:
[]
console
.
log
(
'this.userConfigModal'
,
this
.
userConfigModal
)
},
addUsers
()
{
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
]
this
.
userSelectorVisible
=
false
},
removeUser
(
user
)
{
this
.
userConfigModal
.
selectedUsers
=
this
.
userConfigModal
.
selectedUsers
.
filter
(
u
=>
u
.
user_id
!==
user
.
user_id
)
},
saveUserConfig
()
{
this
.
userConfigModal
.
saving
=
true
const
userIds
=
this
.
userConfigModal
.
selectedUsers
.
map
(
u
=>
u
.
user_id
)
savePermissionUsers
({
permission_code
:
this
.
userConfigModal
.
permissionCode
,
user_ids
:
userIds
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
{
this
.
$Message
.
success
(
'保存成功'
)
this
.
userConfigModal
.
visible
=
false
this
.
loadPermissionConfig
()
}
else
{
this
.
$Notice
.
error
({
title
:
'保存失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}
}).
finally
(()
=>
{
this
.
userConfigModal
.
saving
=
false
})
},
// tplDownload () {
// // 下载物料导入模板
// materialTemplateDownload({}).then(ret => {
// if (ret && ret.data && ret.data.errcode === 0) {
// // const data = ret.data.data
// // 如果后端直接返回文件流需要采用 axios blob 下载,这里假设返回 url 或 blob handled by backend
// // 简单提示或可实现下载逻辑
// this.$Notice.success({ title: '模板已准备,请在后台下载' })
// } else {
// this.$Notice.error({ title: '模板下载失败', desc: ret.data && ret.data.errmsg })
// }
// }).catch(() => {
// this.$Notice.error({ title: '模板下载失败' })
// })
// },
async
tplDownload
()
{
// 下载物料导入模板
try
{
const
response
=
await
axios
.
post
(
'/api/ac/jilinsscgsdp/keyDmUserCategory/templateDownload'
,
{},
{
responseType
:
'blob'
}
)
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
response
.
data
]))
// 创建隐藏的a标签并设置属性
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
link
.
download
=
'办公用品导入模板.xlsx'
// 自定义下载文件名和扩展名
link
.
style
.
display
=
'none'
document
.
body
.
appendChild
(
link
)
// 触发点击下载
link
.
click
()
// 清理
document
.
body
.
removeChild
(
link
)
window
.
URL
.
revokeObjectURL
(
url
)
}
catch
(
error
)
{
console
.
error
(
'下载失败:'
,
error
)
// 可以在这里添加错误提示
}
},
handleBeforeUpload
(
file
)
{
const
fileExt
=
file
.
name
.
split
(
'.'
).
pop
().
toLocaleLowerCase
()
...
...
@@ -899,6 +860,7 @@ export default {
<
style
scoped
>
.key-dm-wrapper
{
padding
:
10px
;
min-height
:
80vh
;
}
.search-div
{
border
:
1px
solid
#dce1e7
;
...
...
src/view/key-person/key_dm_conf/materialSelector.vue
View file @
6391ed84
...
...
@@ -23,14 +23,7 @@
</Row>
</div>
<Table
:data=
"rows"
:loading=
"loading"
@
on-selection-change=
"onSelectionChange"
border
>
<TableColumn
type=
"selection"
width=
"60"
></TableColumn>
<TableColumn
prop=
"material_code"
title=
"物料编码"
align=
"center"
/>
<TableColumn
prop=
"material_name"
title=
"物料名称"
align=
"center"
/>
<TableColumn
prop=
"unit"
title=
"单位"
align=
"center"
width=
"80"
/>
<TableColumn
prop=
"available_quantity"
title=
"可用库存"
align=
"center"
width=
"120"
/>
<TableColumn
prop=
"category_Name"
title=
"分类"
align=
"center"
/>
</Table>
<Table
:data=
"rows"
:loading=
"loading"
:columns=
"columns"
@
on-selection-change=
"onSelectionChange"
border
/>
<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"
/>
...
...
@@ -62,7 +55,15 @@ export default {
pager
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
selectedRows
:
[],
confirming
:
false
,
categoryOptions
:
[]
categoryOptions
:
[],
columns
:
[
{
type
:
'selection'
,
width
:
60
},
{
title
:
'物料编码'
,
key
:
'material_code'
,
align
:
'center'
},
{
title
:
'物料名称'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'单位'
,
key
:
'unit'
,
align
:
'center'
,
width
:
80
},
{
title
:
'可用库存'
,
key
:
'available_quantity'
,
align
:
'center'
,
width
:
120
},
{
title
:
'分类'
,
key
:
'category_Name'
,
align
:
'center'
}
]
}
},
computed
:
{
...
...
@@ -146,5 +147,3 @@ export default {
.mr10
{
margin-right
:
10px
;
}
.page_style
{
margin-top
:
12px
;
text-align
:
right
;
}
</
style
>
src/view/key-person/key_dm_inventory/inbound.vue
View file @
6391ed84
...
...
@@ -82,14 +82,14 @@
<Input
type=
"textarea"
v-model=
"inboundModal.form.remark"
:rows=
"2"
/>
</FormItem>
<h4>
明细(从物料库选择)
</h4>
<Table
:data=
"inboundModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_code"
title=
"物料编码"
/
>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/
>
<
TableColumn
prop=
"inbound_quantity"
title=
"入库数量"
/
>
<TableColumn
prop=
"unit_price"
title=
"单价"
/
>
<TableColumn
prop=
"total_amount"
title=
"总金额
"
/>
<
/Table
>
<h4>
明细(从物料库选择)
<div
style=
"float: right;"
>
<Button
size=
"small"
class=
"mr5"
type=
"primary"
@
click=
"showMaterialSelector = true"
>
添加
</Button
>
<Button
size=
"small"
type=
"error"
@
click=
"deleteSelectedInboundDetails"
>
删除
</Button
>
<
/div
>
</h4
>
<Table
:data=
"inboundModal.details"
:columns=
"inboundDetailColumns"
size=
"small"
border
@
on-selection-change=
"onInboundDetailSelectionChange"
style=
"width: 100%
"
/>
<
MaterialSelector
v-model=
"showMaterialSelector"
:selected=
"[]"
@
on-ok=
"handleInboundMaterialSelectorOk"
@
cancel=
"showMaterialSelector = false"
/
>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"inboundModal.visible=false"
>
取消
</Button>
...
...
@@ -103,11 +103,7 @@
<FormItem
label=
"申请单号"
><span>
{{ returnModal.record.application_no }}
</span></FormItem>
<FormItem
label=
"申请人"
><span>
{{ returnModal.record.applicant_name }}
</span></FormItem>
<FormItem
label=
"归还明细"
>
<Table
:data=
"returnModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/>
<TableColumn
prop=
"apply_quantity"
title=
"申请数量"
/>
<TableColumn
prop=
"returned_quantity"
title=
"归还数量"
/>
</Table>
<Table
:data=
"returnModal.details"
:columns=
"returnDetailColumns"
size=
"small"
border
/>
</FormItem>
</Form>
<div
slot=
"footer"
>
...
...
@@ -122,18 +118,9 @@
<div
v-else
>
<Row
:gutter=
"16"
><Col
span=
"12"
><p><strong>
单号:
</strong>
{{ detailModal.data.inbound_no || detailModal.data.application_no }}
</p></Col></Row>
<Row
class=
"mt8"
><Col
span=
"24"
><h4>
明细
</h4></Col></Row>
<Table
:data=
"detailModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_code"
title=
"物料编码"
/>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/>
<TableColumn
prop=
"inbound_quantity"
title=
"数量"
/>
<TableColumn
prop=
"unit_price"
title=
"单价"
/>
</Table>
<Table
:data=
"detailModal.details"
:columns=
"detailDetailColumns"
size=
"small"
border
/>
<Row
class=
"mt8"
><Col
span=
"24"
><h4>
操作日志
</h4></Col></Row>
<Table
:data=
"detailModal.logs"
size=
"small"
border
>
<TableColumn
prop=
"op_type"
title=
"操作类型"
/>
<TableColumn
prop=
"quantity"
title=
"数量"
/>
<TableColumn
prop=
"create_time"
title=
"时间"
/>
</Table>
<Table
:data=
"detailModal.logs"
:columns=
"detailLogsColumns"
size=
"small"
border
/>
</div>
<div
slot=
"footer"
><Button
type=
"primary"
@
click=
"detailModal.visible=false"
>
关闭
</Button></div>
</Modal>
...
...
@@ -151,9 +138,11 @@ import {
getInventoryList
,
getInboundById
}
from
'@/api/key-dm-inbound'
import
MaterialSelector
from
'@/view/key-person/key_dm_conf/materialSelector.vue'
export
default
{
name
:
'key-dm-inbound-index'
,
components
:
{
MaterialSelector
},
data
()
{
return
{
activeTab
:
'inbound'
,
...
...
@@ -186,6 +175,67 @@ export default {
{
title
:
'可用'
,
key
:
'available_quantity'
,
align
:
'center'
},
{
title
:
'借出'
,
key
:
'borrowed_quantity'
,
align
:
'center'
}
],
// 模态窗口内表格列定义
inboundDetailColumns
:
[
{
type
:
'selection'
,
width
:
60
},
{
title
:
'物料编码'
,
key
:
'material_code'
,
minWidth
:
120
},
{
title
:
'物料名称'
,
key
:
'material_name'
,
minWidth
:
150
},
{
title
:
'入库数量'
,
key
:
'inbound_quantity'
,
minWidth
:
120
,
render
:
(
h
,
params
)
=>
{
return
h
(
'InputNumber'
,
{
props
:
{
value
:
params
.
row
.
inbound_quantity
||
0
,
min
:
0
,
precision
:
0
},
style
:
{
width
:
'100px'
},
on
:
{
input
:
(
val
)
=>
{
params
.
row
.
inbound_quantity
=
val
||
0
params
.
row
.
total_amount
=
((
params
.
row
.
inbound_quantity
||
0
)
*
(
params
.
row
.
unit_price
||
0
)).
toFixed
(
2
)
}
}
})
}},
{
title
:
'单价'
,
key
:
'unit_price'
,
minWidth
:
120
,
render
:
(
h
,
params
)
=>
{
return
h
(
'InputNumber'
,
{
props
:
{
value
:
params
.
row
.
unit_price
||
0
,
min
:
0
,
precision
:
2
},
style
:
{
width
:
'100px'
},
on
:
{
input
:
(
val
)
=>
{
params
.
row
.
unit_price
=
val
||
0
params
.
row
.
total_amount
=
((
params
.
row
.
inbound_quantity
||
0
)
*
(
params
.
row
.
unit_price
||
0
)).
toFixed
(
2
)
}
}
})
}},
{
title
:
'总金额'
,
key
:
'total_amount'
,
minWidth
:
120
,
render
:
(
h
,
params
)
=>
{
const
amount
=
((
params
.
row
.
inbound_quantity
||
0
)
*
(
params
.
row
.
unit_price
||
0
)).
toFixed
(
2
)
return
h
(
'span'
,
amount
)
}}
],
returnDetailColumns
:
[
{
title
:
'物料名称'
,
key
:
'material_name'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
},
{
title
:
'归还数量'
,
key
:
'returned_quantity'
}
],
detailDetailColumns
:
[
{
title
:
'物料编码'
,
key
:
'material_code'
},
{
title
:
'物料名称'
,
key
:
'material_name'
},
{
title
:
'数量'
,
key
:
'inbound_quantity'
},
{
title
:
'单价'
,
key
:
'unit_price'
}
],
detailLogsColumns
:
[
{
title
:
'操作类型'
,
key
:
'op_type'
},
{
title
:
'数量'
,
key
:
'quantity'
},
{
title
:
'时间'
,
key
:
'create_time'
}
],
// 选择器控制与已选明细
showMaterialSelector
:
false
,
inboundSelectedDetails
:
[],
inboundModal
:
{
visible
:
false
,
isEdit
:
false
,
saving
:
false
,
form
:
{},
details
:
[]
},
returnModal
:
{
visible
:
false
,
record
:
{},
details
:
[],
saving
:
false
},
detailModal
:
{
visible
:
false
,
loading
:
false
,
data
:
{},
details
:
[],
logs
:
[]
}
...
...
@@ -222,6 +272,40 @@ export default {
this
.
inboundModal
.
details
=
[]
this
.
inboundModal
.
visible
=
true
},
onInboundDetailSelectionChange
(
list
)
{
this
.
inboundSelectedDetails
=
list
||
[]
},
handleInboundMaterialSelectorOk
(
selectedRows
)
{
if
(
!
Array
.
isArray
(
selectedRows
)
||
selectedRows
.
length
===
0
)
{
this
.
$Message
.
warning
(
'未选择物料'
)
return
}
selectedRows
.
forEach
(
sel
=>
{
const
code
=
sel
.
material_code
const
exist
=
this
.
inboundModal
.
details
.
find
(
d
=>
d
.
material_code
===
code
)
if
(
exist
)
{
exist
.
inbound_quantity
=
Number
(
exist
.
inbound_quantity
||
0
)
+
1
}
else
{
this
.
inboundModal
.
details
.
push
({
material_code
:
sel
.
material_code
,
material_name
:
sel
.
material_name
,
inbound_quantity
:
0
,
unit_price
:
0
,
total_amount
:
0
})
}
})
this
.
showMaterialSelector
=
false
},
deleteSelectedInboundDetails
()
{
if
(
!
this
.
inboundSelectedDetails
||
this
.
inboundSelectedDetails
.
length
===
0
)
{
this
.
$Message
.
warning
(
'请先选择要删除的明细行'
)
return
}
const
toRemoveCodes
=
this
.
inboundSelectedDetails
.
map
(
r
=>
r
.
material_code
)
this
.
inboundModal
.
details
=
this
.
inboundModal
.
details
.
filter
(
d
=>
!
toRemoveCodes
.
includes
(
d
.
material_code
))
this
.
inboundSelectedDetails
=
[]
},
openEdit
(
row
)
{
this
.
inboundModal
.
isEdit
=
true
getInboundById
({
id
:
row
.
id
}).
then
(
ret
=>
{
...
...
src/view/key-person/key_dm_inventory/index.vue
View file @
6391ed84
...
...
@@ -67,13 +67,14 @@
</FormItem>
<h4>
申请明细
</h4>
<Table
:data=
"applyModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_code"
title=
"物料编码"
/>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/>
<TableColumn
prop=
"apply_quantity"
title=
"申请数量"
/>
<TableColumn
prop=
"unit"
title=
"单位"
/>
<TableColumn
prop=
"issue_remark"
title=
"备注"
/>
</Table>
<Row
type=
"flex"
justify=
"end"
class=
"mb8"
>
<Col>
<Button
size=
"small"
class=
"mr5"
type=
"primary"
@
click=
"showMaterialSelector = true"
>
添加
</Button>
<Button
size=
"small"
type=
"error"
@
click=
"deleteSelectedDetails"
>
删除
</Button>
</Col>
</Row>
<Table
:data=
"applyModal.details"
:columns=
"applyDetailColumns"
size=
"small"
border
@
on-selection-change=
"onApplyDetailSelectionChange"
/>
<MaterialSelector
v-model=
"showMaterialSelector"
:selected=
"[]"
@
on-ok=
"handleMaterialSelectorOk"
@
cancel=
"showMaterialSelector = false"
/>
</Form>
<div
slot=
"footer"
>
<Button
@
click=
"applyModal.visible=false"
>
取消
</Button>
...
...
@@ -87,12 +88,7 @@
<FormItem
label=
"申请单号"
><span>
{{ approveModal.record.application_no }}
</span></FormItem>
<FormItem
label=
"申请人"
><span>
{{ approveModal.record.applicant_name }}
</span></FormItem>
<FormItem
label=
"申请明细"
>
<Table
:data=
"approveModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/>
<TableColumn
prop=
"apply_quantity"
title=
"申请数量"
/>
<TableColumn
prop=
"unit"
title=
"单位"
/>
<TableColumn
prop=
"available_quantity"
title=
"可用库存"
/>
</Table>
<Table
:data=
"approveModal.details"
:columns=
"approveDetailColumns"
size=
"small"
border
/>
</FormItem>
<FormItem
label=
"审批意见"
>
<Input
type=
"textarea"
v-model=
"approveModal.opinion"
placeholder=
"驳回时必填"
/>
...
...
@@ -112,20 +108,9 @@
<Row
:gutter=
"16"
><Col
span=
"12"
><p><strong>
申请人:
</strong>
{{ detailModal.data.applicant_name }}
</p></Col><Col
span=
"12"
><p><strong>
部门:
</strong>
{{ detailModal.data.department_name }}
</p></Col></Row>
<Row
class=
"mt8"
><Col
span=
"24"
><p><strong>
领用用途:
</strong>
{{ detailModal.data.borrow_purpose }}
</p></Col></Row>
<Row
class=
"mt8"
><Col
span=
"24"
><h4>
明细
</h4></Col></Row>
<Table
:data=
"detailModal.details"
size=
"small"
border
>
<TableColumn
prop=
"material_code"
title=
"物料编码"
/>
<TableColumn
prop=
"material_name"
title=
"物料名称"
/>
<TableColumn
prop=
"apply_quantity"
title=
"申请数量"
/>
<TableColumn
prop=
"unit"
title=
"单位"
/>
<TableColumn
prop=
"returned_quantity"
title=
"已归还"
/>
</Table>
<Table
:data=
"detailModal.details"
:columns=
"detailDetailColumns"
size=
"small"
border
/>
<Row
class=
"mt8"
><Col
span=
"24"
><h4>
审批记录
</h4></Col></Row>
<Table
:data=
"detailModal.logs"
size=
"small"
border
>
<TableColumn
prop=
"op_type"
title=
"操作类型"
/>
<TableColumn
prop=
"quantity"
title=
"数量"
/>
<TableColumn
prop=
"create_time"
title=
"时间"
/>
<TableColumn
prop=
"create_by"
title=
"操作人"
/>
</Table>
<Table
:data=
"detailModal.logs"
:columns=
"detailLogsColumns"
size=
"small"
border
/>
</div>
<div
slot=
"footer"
><Button
type=
"primary"
@
click=
"detailModal.visible=false"
>
关闭
</Button></div>
</Modal>
...
...
@@ -143,9 +128,11 @@ import {
rejectBorrow
,
getBorrowById
}
from
'@/api/key-dm-inventory'
import
MaterialSelector
from
'@/view/key-person/key_dm_conf/materialSelector.vue'
export
default
{
name
:
'key-dm-inventory-index'
,
components
:
{
MaterialSelector
},
data
()
{
return
{
activeTab
:
'apply'
,
...
...
@@ -180,6 +167,37 @@ export default {
{
title
:
'审批完成时间'
,
key
:
'approval_complete_time'
,
align
:
'center'
},
{
title
:
'操作'
,
slot
:
'action'
,
width
:
100
,
align
:
'center'
}
],
// 模态窗口内表格列定义
applyDetailColumns
:
[
{
type
:
'selection'
,
width
:
60
},
{
title
:
'物料编码'
,
key
:
'material_code'
},
{
title
:
'物料名称'
,
key
:
'material_name'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
},
{
title
:
'单位'
,
key
:
'unit'
},
{
title
:
'备注'
,
key
:
'issue_remark'
}
],
approveDetailColumns
:
[
{
title
:
'物料名称'
,
key
:
'material_name'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
},
{
title
:
'单位'
,
key
:
'unit'
},
{
title
:
'可用库存'
,
key
:
'available_quantity'
}
],
detailDetailColumns
:
[
{
title
:
'物料编码'
,
key
:
'material_code'
},
{
title
:
'物料名称'
,
key
:
'material_name'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
},
{
title
:
'单位'
,
key
:
'unit'
},
{
title
:
'已归还'
,
key
:
'returned_quantity'
}
],
detailLogsColumns
:
[
{
title
:
'操作类型'
,
key
:
'op_type'
},
{
title
:
'数量'
,
key
:
'quantity'
},
{
title
:
'时间'
,
key
:
'create_time'
},
{
title
:
'操作人'
,
key
:
'create_by'
}
],
// 选择器控制与已选明细
showMaterialSelector
:
false
,
applySelectedDetails
:
[],
applyModal
:
{
visible
:
false
,
isEdit
:
false
,
saving
:
false
,
form
:
{},
details
:
[]
},
approveModal
:
{
visible
:
false
,
record
:
{},
details
:
[],
opinion
:
''
,
submitting
:
false
},
detailModal
:
{
visible
:
false
,
loading
:
false
,
data
:
{},
details
:
[],
logs
:
[]
}
...
...
@@ -227,6 +245,41 @@ export default {
})
this
.
applyModal
.
visible
=
true
},
onApplyDetailSelectionChange
(
list
)
{
this
.
applySelectedDetails
=
list
||
[]
},
handleMaterialSelectorOk
(
selectedRows
)
{
if
(
!
Array
.
isArray
(
selectedRows
)
||
selectedRows
.
length
===
0
)
{
this
.
$Message
.
warning
(
'未选择物料'
)
return
}
selectedRows
.
forEach
(
sel
=>
{
const
code
=
sel
.
material_code
const
exist
=
this
.
applyModal
.
details
.
find
(
d
=>
d
.
material_code
===
code
)
if
(
exist
)
{
exist
.
apply_quantity
=
Number
(
exist
.
apply_quantity
||
0
)
+
1
}
else
{
this
.
applyModal
.
details
.
push
({
material_code
:
sel
.
material_code
,
material_name
:
sel
.
material_name
,
apply_quantity
:
1
,
unit
:
sel
.
unit
,
issue_remark
:
''
,
available_quantity
:
sel
.
available_quantity
||
0
})
}
})
this
.
showMaterialSelector
=
false
},
deleteSelectedDetails
()
{
if
(
!
this
.
applySelectedDetails
||
this
.
applySelectedDetails
.
length
===
0
)
{
this
.
$Message
.
warning
(
'请先选择要删除的明细行'
)
return
}
const
toRemoveCodes
=
this
.
applySelectedDetails
.
map
(
r
=>
r
.
material_code
)
this
.
applyModal
.
details
=
this
.
applyModal
.
details
.
filter
(
d
=>
!
toRemoveCodes
.
includes
(
d
.
material_code
))
this
.
applySelectedDetails
=
[]
},
saveApplication
()
{
this
.
applyModal
.
saving
=
true
const
payload
=
Object
.
assign
({},
this
.
applyModal
.
form
,
{
details
:
this
.
applyModal
.
details
})
...
...
src/view/key-person/key_dm_inventory/stats.vue
View file @
6391ed84
<
template
>
<div
class=
"key-dm-stats-wrapper"
>
<Tabs
v-model=
"activeTab"
@
on-click=
"handleTabChange"
>
<Tabs
v-model=
"activeTab"
@
on-click=
"handleTabChange"
class=
"tabsCls"
>
<TabPane
label=
"办公用品使用统计"
name=
"usage"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
:span=
"
8
"
>
<span>
时间段
:
</span>
<DatePicker
v-model=
"usage
Range"
type=
"daterange"
style=
"width:70%
"
/>
</Col
>
<Col
:span=
"8"
>
<Col
:span=
"
20
"
>
<span>
开始
:
</span>
<DatePicker
v-model=
"usage
Start"
type=
"date"
style=
"min-width:110px;margin-right:20px
"
/>
<span>
结束:
</span
>
<DatePicker
v-model=
"usageEnd"
type=
"date"
style=
"min-width:110px;margin-right:20px"
/
>
<span>
物料:
</span>
<Input
v-model=
"usageMaterial"
placeholder=
"物料名称或编码"
style=
"width:
70%
"
/>
<Input
v-model=
"usageMaterial"
placeholder=
"物料名称或编码"
style=
"width:
150px
"
/>
</Col>
<Col
:span=
"
8
"
class=
"text-right"
>
<Col
:span=
"
4
"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"loadUsage"
>
统计
</Button>
<Button
@
click=
"resetUsage"
>
重置
</Button>
</Col>
...
...
@@ -28,9 +28,11 @@
<TabPane
label=
"工作量统计"
name=
"workload"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
:span=
"10"
>
<span>
时间段:
</span>
<DatePicker
v-model=
"workRange"
type=
"daterange"
style=
"width:70%"
/>
<Col
:span=
"18"
>
<span>
开始:
</span>
<DatePicker
v-model=
"workStart"
type=
"date"
style=
"min-width:110px;margin-right:20px"
/>
<span>
结束:
</span>
<DatePicker
v-model=
"workEnd"
type=
"date"
style=
"min-width:110px;margin-right:20px"
/>
</Col>
<Col
:span=
"6"
class=
"text-right"
>
<Button
type=
"primary"
class=
"mr10"
@
click=
"loadWorkload"
>
统计
</Button>
...
...
@@ -49,25 +51,26 @@
<!-- 使用明细弹窗 -->
<Modal
v-model=
"detailModal.visible"
title=
"明细"
width=
"800"
>
<Table
:data=
"detailModal.rows"
size=
"small"
border
>
<TableColumn
v-for=
"col in detailModal.columns"
:key=
"col.key"
:prop=
"col.key"
:title=
"col.title"
/>
</Table>
<Table
:data=
"detailModal.rows"
:columns=
"detailModal.columns"
size=
"small"
border
/>
<div
slot=
"footer"
><Button
type=
"primary"
@
click=
"detailModal.visible=false"
>
关闭
</Button></div>
</Modal>
</div>
</template>
<
script
>
import
{
getUsageStats
,
getUsageDetails
,
getWorkloadStats
,
getWorkloadDetails
}
from
'@/api/key-dm-stats'
import
{
getUsageStats
,
getUsageDetails
,
getWorkloadStats
,
getWorkloadDetails
}
from
'@/api/key-dm'
import
{
normalizeVisitTimeValue
}
from
'@/view/key-person/key_dm_conf/dates.js'
export
default
{
name
:
'key-dm-stats-index'
,
data
()
{
return
{
activeTab
:
'usage'
,
usageRange
:
[],
usageStart
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
(),
1
),
usageEnd
:
new
Date
(),
usageMaterial
:
''
,
workRange
:
[],
workStart
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
(),
1
),
workEnd
:
new
Date
(),
tables
:
{
usage
:
[],
workload
:
[]
},
loading
:
{
usage
:
false
,
workload
:
false
},
usageColumns
:
[
...
...
@@ -87,48 +90,83 @@ export default {
{
title
:
'请假时长(天)'
,
key
:
'leave_duration'
,
align
:
'center'
},
{
title
:
'操作'
,
slot
:
'action'
,
width
:
160
,
align
:
'center'
}
],
detailModal
:
{
visible
:
false
,
rows
:
[],
columns
:
[]
}
detailModal
:
{
visible
:
false
,
rows
:
[],
columns
:
[]
}
}
},
created
()
{
this
.
loadUsage
()
},
methods
:
{
handleTabChange
(
name
)
{
this
.
activeTab
=
name
if
(
name
===
'usage'
)
{
this
.
loadUsage
()
}
else
{
this
.
loadWorkload
()
}
},
loadUsage
()
{
this
.
loading
.
usage
=
true
const
params
=
{
start
:
this
.
usageRange
[
0
],
end
:
this
.
usageRange
[
1
],
material
:
this
.
usageMaterial
}
getUsageStats
({
params
}).
then
(
ret
=>
{
const
st
=
this
.
usageStart
?
normalizeVisitTimeValue
(
this
.
usageStart
)
:
null
const
et
=
this
.
usageEnd
?
normalizeVisitTimeValue
(
this
.
usageEnd
)
:
null
const
params
=
{
start
:
st
,
end
:
et
,
material
:
this
.
usageMaterial
}
getUsageStats
(
params
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
this
.
tables
.
usage
=
ret
.
data
.
data
||
[]
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}).
finally
(()
=>
{
this
.
loading
.
usage
=
false
})
},
resetUsage
()
{
this
.
usage
Range
=
[]
;
this
.
usageMaterial
=
''
;
this
.
tables
.
usage
=
[]
},
resetUsage
()
{
this
.
usage
Start
=
null
;
this
.
usageEnd
=
null
;
this
.
usageMaterial
=
''
;
this
.
tables
.
usage
=
[]
},
openUsageDetail
(
row
)
{
this
.
detailModal
.
columns
=
[{
key
:
'user_name'
,
title
:
'人员'
},
{
key
:
'quantity'
,
title
:
'数量'
},
{
key
:
'material_name'
,
title
:
'物料'
},
{
key
:
'department_name'
,
title
:
'部门'
}]
this
.
detailModal
.
columns
=
[
{
title
:
'部门'
,
key
:
'department_name'
,
align
:
'center'
},
{
title
:
'人员'
,
key
:
'user_name'
,
align
:
'center'
},
{
title
:
'物料'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'申请数量'
,
key
:
'apply_quantity'
,
align
:
'center'
},
{
title
:
'已归还数量'
,
key
:
'returned_quantity'
,
align
:
'center'
}
]
this
.
detailModal
.
visible
=
true
getUsageDetails
({
params
:
{
start
:
this
.
usageRange
[
0
],
end
:
this
.
usageRange
[
1
],
material
:
this
.
usageMaterial
,
department
:
row
.
department_id
}
}).
then
(
ret
=>
{
const
st
=
this
.
usageStart
?
normalizeVisitTimeValue
(
this
.
usageStart
)
:
null
const
et
=
this
.
usageEnd
?
normalizeVisitTimeValue
(
this
.
usageEnd
)
:
null
getUsageDetails
({
start
:
st
,
end
:
et
,
material
:
row
.
material_id
,
department
:
row
.
department_id
}).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
this
.
detailModal
.
rows
=
ret
.
data
.
data
||
[]
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
})
},
loadWorkload
()
{
this
.
loading
.
workload
=
true
const
params
=
{
start
:
this
.
workRange
[
0
],
end
:
this
.
workRange
[
1
]
}
getWorkloadStats
({
params
}).
then
(
ret
=>
{
const
st
=
this
.
workStart
?
normalizeVisitTimeValue
(
this
.
workStart
)
:
null
const
et
=
this
.
workEnd
?
normalizeVisitTimeValue
(
this
.
workEnd
)
:
null
const
params
=
{
start
:
st
,
end
:
et
}
getWorkloadStats
(
params
).
then
(
ret
=>
{
if
(
ret
.
data
&&
ret
.
data
.
errcode
===
0
)
this
.
tables
.
workload
=
ret
.
data
.
data
||
[]
else
this
.
$Notice
.
error
({
title
:
'查询失败'
,
desc
:
ret
.
data
&&
ret
.
data
.
errmsg
})
}).
finally
(()
=>
{
this
.
loading
.
workload
=
false
})
},
resetWorkload
()
{
this
.
work
Range
=
[]
;
this
.
tables
.
workload
=
[]
},
resetWorkload
()
{
this
.
work
Start
=
null
;
this
.
workEnd
=
null
;
this
.
tables
.
workload
=
[]
},
openWorkloadDetail
(
row
,
type
)
{
const
st
=
this
.
workStart
?
normalizeVisitTimeValue
(
this
.
workStart
)
:
null
const
et
=
this
.
workEnd
?
normalizeVisitTimeValue
(
this
.
workEnd
)
:
null
if
(
type
===
'leave'
)
{
this
.
detailModal
.
columns
=
[{
key
:
'user_name'
,
title
:
'人员'
},
{
key
:
'start_time'
,
title
:
'开始'
},
{
key
:
'end_time'
,
title
:
'结束'
},
{
key
:
'duration'
,
title
:
'时长'
}]
getWorkloadDetails
({
params
:
{
user_id
:
row
.
user_id
,
start
:
this
.
workRange
[
0
],
end
:
this
.
workRange
[
1
],
type
:
'leave'
}
}).
then
(
ret
=>
{
this
.
detailModal
.
columns
=
[
{
title
:
'人员'
,
key
:
'user_name'
,
align
:
'center'
},
{
title
:
'开始'
,
key
:
'start_time'
,
align
:
'center'
},
{
title
:
'结束'
,
key
:
'end_time'
,
align
:
'center'
},
{
title
:
'时长'
,
key
:
'duration'
,
align
:
'center'
}
]
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
=
[{
key
:
'application_no'
,
title
:
'申请单号'
},
{
key
:
'material_name'
,
title
:
'物料'
},
{
key
:
'apply_quantity'
,
title
:
'数量'
}]
getWorkloadDetails
({
params
:
{
user_id
:
row
.
user_id
,
start
:
this
.
workRange
[
0
],
end
:
this
.
workRange
[
1
],
type
:
'inventory'
}
}).
then
(
ret
=>
{
this
.
detailModal
.
columns
=
[
{
title
:
'申请单号'
,
key
:
'application_no'
,
align
:
'center'
},
{
title
:
'物料'
,
key
:
'material_name'
,
align
:
'center'
},
{
title
:
'数量'
,
key
:
'apply_quantity'
,
align
:
'center'
}
]
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
})
})
}
...
...
@@ -138,7 +176,8 @@ export default {
</
script
>
<
style
scoped
>
.key-dm-stats-wrapper
{
padding
:
10px
;
}
.key-dm-stats-wrapper
{
padding
:
10px
;
min-height
:
380px
;}
.tabsCls
{
min-height
:
380px
;}
.search-div
{
border
:
1px
solid
#dce1e7
;
padding
:
12px
;
margin-bottom
:
12px
;
background-color
:
#f8fbff
;
}
.mr10
{
margin-right
:
10px
;
}
.text-right
{
text-align
:
right
;
}
...
...
src/view/key-person/key_dm_leave/index.vue
View file @
6391ed84
<
template
>
<div
class=
"key-dm-leave-wrapper"
>
<Tabs
v-model=
"activeTab"
@
on-click=
"handleTabChange"
>
<Tabs
v-model=
"activeTab"
@
on-click=
"handleTabChange"
class=
"tabsCls"
>
<TabPane
label=
"请假申请"
name=
"apply"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
>
...
...
@@ -71,11 +71,11 @@
<TabPane
label=
"请假统计"
name=
"stats"
>
<div
class=
"search-div"
>
<Row
type=
"flex"
:gutter=
"16"
align=
"middle"
>
<Col
span=
"
8
"
>
<span>
时间段
:
</span>
<DatePicker
v-model=
"stats
Range"
type=
"daterange"
placeholder=
"选择时间段"
style=
"width:70%
"
/>
</Col
>
<Col
span=
"8"
>
<Col
span=
"
16
"
>
<span>
开始
:
</span>
<DatePicker
v-model=
"stats
Start"
type=
"date"
placeholder=
"开始日期"
style=
"min-width:110px;margin-right:20px
"
/>
<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%"
/>
</Col>
...
...
@@ -271,7 +271,8 @@ export default {
approveModal
:
{
visible
:
false
,
record
:
{},
comment
:
''
,
submitting
:
false
},
transferModal
:
{
visible
:
false
,
selectedApprover
:
''
,
comment
:
''
,
processing
:
false
,
record
:
{}
},
detailModal
:
{
visible
:
false
,
loading
:
false
,
data
:
{},
approvals
:
[]
},
statsRange
:
[],
statsStart
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
(),
1
),
statsEnd
:
new
Date
(),
statsDept
:
''
}
},
...
...
@@ -574,8 +575,8 @@ export default {
loadStats
()
{
this
.
loading
.
stats
=
true
const
params
=
{
start
:
this
.
stats
Range
&&
this
.
statsRange
[
0
]
,
end
:
this
.
stats
Range
&&
this
.
statsRange
[
1
]
,
start
:
this
.
stats
Start
,
end
:
this
.
stats
End
,
department
:
this
.
statsDept
}
getLeaveStats
({
params
}).
then
(
ret
=>
{
...
...
@@ -588,7 +589,8 @@ export default {
}).
finally
(()
=>
{
this
.
loading
.
stats
=
false
})
},
resetStats
()
{
this
.
statsRange
=
[]
this
.
statsStart
=
null
this
.
statsEnd
=
null
this
.
statsDept
=
''
this
.
tables
.
stats
=
[]
}
...
...
@@ -597,7 +599,8 @@ export default {
</
script
>
<
style
scoped
>
.key-dm-leave-wrapper
{
padding
:
10px
;
}
.key-dm-leave-wrapper
{
padding
:
10px
;
min-height
:
380px
;}
.tabsCls
{
min-height
:
380px
;}
.search-div
{
border
:
1px
solid
#dce1e7
;
padding
:
12px
;
margin-bottom
:
12px
;
background-color
:
#f8fbff
;
}
.mr10
{
margin-right
:
10px
;
}
.text-right
{
text-align
:
right
;
}
...
...
src/view/key-person/key_dm_user/userMultiSelector.vue
0 → 100644
View file @
6391ed84
<
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=
"请输入姓名"
@
on-enter=
"handleSearch"
/>
</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"
@
on-selection-change=
"onSelectionChange"
border
/>
<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"
>
确定(
{{
selectedRows
.
length
}}
)
</Button>
</div>
</Modal>
</
template
>
<
script
>
import
{
getUserMultiSelectorList
}
from
'@/api/key-dm-user'
export
default
{
name
:
'user-multi-selector'
,
props
:
{
// v-model: value 控制显示
value
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
visibleInternal
:
false
,
filters
:
{
name
:
''
},
rows
:
[],
loading
:
false
,
pager
:
{
pageNo
:
1
,
pageSize
:
10
,
totalRecord
:
0
},
selectedRows
:
[],
confirming
:
false
,
columns
:
[
{
type
:
'selection'
,
width
:
60
,
align
:
'center'
},
{
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
}
]
}
},
computed
:
{
visible
:
{
get
()
{
return
this
.
value
},
set
(
v
)
{
this
.
$emit
(
'input'
,
v
)
}
}
},
watch
:
{
visible
(
v
)
{
if
(
v
)
{
this
.
pager
.
pageNo
=
1
this
.
selectedRows
=
[]
this
.
filters
.
name
=
''
this
.
fetchList
()
}
}
},
methods
:
{
fetchList
()
{
this
.
loading
=
true
const
payload
=
{
pageNo
:
this
.
pager
.
pageNo
,
pageSize
:
this
.
pager
.
pageSize
,
params
:
this
.
filters
}
getUserMultiSelectorList
(
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
()
},
onSelectionChange
(
list
)
{
this
.
selectedRows
=
list
||
[]
},
handleCancel
()
{
this
.
$emit
(
'cancel'
)
this
.
$emit
(
'input'
,
false
)
},
handleConfirm
()
{
if
(
this
.
selectedRows
.
length
===
0
)
{
this
.
$Message
.
warning
(
'请先选择人员'
)
return
}
this
.
confirming
=
true
// emit selected users to parent
this
.
$emit
(
'on-ok'
,
this
.
selectedRows
)
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论