feat: 完善批量修改填写人、审核页面优化、人员管理等功能
- 批量修改填写人:添加左侧分类列表、折叠功能、暂存和重新分配 - 审核页面:添加折叠和分页功能 - 查询分析页面:添加单位列显示 - 人员管理:创建独立页面,支持搜索、分页、批量操作 - 修复各种UI和功能问题
This commit is contained in:
parent
4e1bef2888
commit
46b01b4504
4
.arts/settings.json
Normal file
4
.arts/settings.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"clawMode.mode": "editor",
|
||||||
|
"workbench.activityBar.location": "default"
|
||||||
|
}
|
||||||
2
.env
2
.env
@ -1,3 +1,3 @@
|
|||||||
VUE_APP_BASE_DOMAIN=http://dcloud-demo.definesys.cn:31213
|
VUE_APP_BASE_DOMAIN=http://dcloud-demo.definesys.cn:31213
|
||||||
VUE_APP_TENANT_ID=254638499280453633
|
VUE_APP_TENANT_ID=254638499280453633
|
||||||
VUE_APP_PUBLIC_PATH=/app/
|
VUE_APP_PUBLIC_PATH=/
|
||||||
36
README.en.md
36
README.en.md
@ -1,36 +0,0 @@
|
|||||||
# yuchai
|
|
||||||
|
|
||||||
#### Description
|
|
||||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
|
||||||
|
|
||||||
#### Software Architecture
|
|
||||||
Software architecture description
|
|
||||||
|
|
||||||
#### Installation
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### Instructions
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### Contribution
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create Feat_xxx branch
|
|
||||||
3. Commit your code
|
|
||||||
4. Create Pull Request
|
|
||||||
|
|
||||||
|
|
||||||
#### Gitee Feature
|
|
||||||
|
|
||||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
|
||||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
|
||||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
|
||||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
|
||||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
|
||||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
|
||||||
39
README.md
39
README.md
@ -1,39 +0,0 @@
|
|||||||
# yuchai
|
|
||||||
|
|
||||||
#### 介绍
|
|
||||||
{**以下是 Gitee 平台说明,您可以替换此简介**
|
|
||||||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
|
||||||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
|
||||||
|
|
||||||
#### 软件架构
|
|
||||||
软件架构说明
|
|
||||||
|
|
||||||
|
|
||||||
#### 安装教程
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### 使用说明
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### 参与贡献
|
|
||||||
|
|
||||||
1. Fork 本仓库
|
|
||||||
2. 新建 Feat_xxx 分支
|
|
||||||
3. 提交代码
|
|
||||||
4. 新建 Pull Request
|
|
||||||
|
|
||||||
|
|
||||||
#### 特技
|
|
||||||
|
|
||||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
|
||||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
|
||||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
|
||||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
|
||||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
|
||||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -142,6 +142,13 @@
|
|||||||
"title": "权限管理"
|
"title": "权限管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"apaas-custom-roleMemberManagement":{
|
||||||
|
"name": "apaas-custom-roleMemberManagement",
|
||||||
|
"path": "apaas-custom-roleMemberManagement",
|
||||||
|
"meta": {
|
||||||
|
"title": "人员管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
"apaas-custom-checkPersonPermission":{
|
"apaas-custom-checkPersonPermission":{
|
||||||
"name": "apaas-custom-checkPersonPermission",
|
"name": "apaas-custom-checkPersonPermission",
|
||||||
"path": "apaas-custom-checkPersonPermission",
|
"path": "apaas-custom-checkPersonPermission",
|
||||||
|
|||||||
37797
package-lock.json
generated
37797
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,6 @@
|
|||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"husky": "^4.2.5",
|
"husky": "^4.2.5",
|
||||||
"lint-staged": "^9.5.0",
|
"lint-staged": "^9.5.0",
|
||||||
"node-sass": "^4.12.0",
|
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"progress-bar-webpack-plugin": "^2.1.0",
|
"progress-bar-webpack-plugin": "^2.1.0",
|
||||||
|
|||||||
@ -134,5 +134,17 @@ export default {
|
|||||||
GET_DEPT_OF_USER: {
|
GET_DEPT_OF_USER: {
|
||||||
url: '/custom/responsible/getResponsibleDepartment',
|
url: '/custom/responsible/getResponsibleDepartment',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
|
},
|
||||||
|
UPDATE_TEMPLATE_ORDER: {
|
||||||
|
url: '/custom/template/batchUpdateTemplateOrder',
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
BATCH_UPDATE_DEPARTMENT: {
|
||||||
|
url: '/custom/todoTaskPojo/batchUpdateDepartment',
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
SAVE_FILLED_BY_TEMP: {
|
||||||
|
url: '/custom/engineParamDetailPojo/saveFilledByTemp',
|
||||||
|
method: 'post'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,5 +64,20 @@ export default {
|
|||||||
GET_ROLE_CONTROL_LIST: {
|
GET_ROLE_CONTROL_LIST: {
|
||||||
url: '/custom/permission/selectPersByRole',
|
url: '/custom/permission/selectPersByRole',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
|
},
|
||||||
|
// 获取角色成员列表
|
||||||
|
GET_ROLE_MEMBERS: {
|
||||||
|
url: '/custom/permission/getRoleMembers',
|
||||||
|
method: 'get'
|
||||||
|
},
|
||||||
|
// 添加角色成员
|
||||||
|
ADD_ROLE_MEMBERS: {
|
||||||
|
url: '/custom/permission/addRoleMembers',
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
// 删除角色成员
|
||||||
|
DELETE_ROLE_MEMBERS: {
|
||||||
|
url: '/custom/permission/deleteRoleMembers',
|
||||||
|
method: 'post'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,6 +142,13 @@
|
|||||||
"title": "权限管理"
|
"title": "权限管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"apaas-custom-roleMemberManagement":{
|
||||||
|
"name": "apaas-custom-roleMemberManagement",
|
||||||
|
"path": "apaas-custom-roleMemberManagement",
|
||||||
|
"meta": {
|
||||||
|
"title": "人员管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
"apaas-custom-checkPersonPermission":{
|
"apaas-custom-checkPersonPermission":{
|
||||||
"name": "apaas-custom-checkPersonPermission",
|
"name": "apaas-custom-checkPersonPermission",
|
||||||
"path": "apaas-custom-checkPersonPermission",
|
"path": "apaas-custom-checkPersonPermission",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -32,10 +32,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="detail-content">
|
<div class="detail-content">
|
||||||
<section class="block-section">
|
<section class="block-section">
|
||||||
<div class="section-title">
|
<div class="section-title" @click="toggleBasicInfo">
|
||||||
基础信息
|
基础信息
|
||||||
|
<i :class="basicInfoCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-grid">
|
<div v-show="!basicInfoCollapsed" class="info-grid">
|
||||||
<!-- 流程主题单独一行 -->
|
<!-- 流程主题单独一行 -->
|
||||||
<div class="info-item-full">
|
<div class="info-item-full">
|
||||||
<span class="label">流程主题</span>
|
<span class="label">流程主题</span>
|
||||||
@ -87,10 +88,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="block-section">
|
<section class="block-section">
|
||||||
<div class="section-title">
|
<div class="section-title" @click="toggleDetailInfo">
|
||||||
详细信息
|
详细信息
|
||||||
|
<i :class="detailInfoCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-grid">
|
<div v-show="!detailInfoCollapsed" class="info-grid">
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<span class="label">产品型号</span>
|
<span class="label">产品型号</span>
|
||||||
@ -157,10 +159,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="block-section">
|
<section class="block-section">
|
||||||
<div class="section-title">
|
<div class="section-title" @click="toggleApprovalContent">
|
||||||
审批内容
|
审批内容
|
||||||
|
<i :class="approvalContentCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="changeTable || []" border class="change-table" :max-height="500">
|
<div v-show="!approvalContentCollapsed">
|
||||||
|
<el-table :data="changeTable || []" border class="change-table" :max-height="500">
|
||||||
<el-table-column label="序号" type="index" width="60" />
|
<el-table-column label="序号" type="index" width="60" />
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="subsystemName"
|
prop="subsystemName"
|
||||||
@ -192,26 +196,31 @@
|
|||||||
<el-table-column prop="changeComment" label="修改描述" min-width="160">
|
<el-table-column prop="changeComment" label="修改描述" min-width="160">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-pagination
|
<div class="pagination-wrapper">
|
||||||
v-if="changeTableTotal > 0"
|
<el-pagination
|
||||||
class="pagination-wrapper"
|
:current-page="changeTablePageNumber"
|
||||||
:current-page="changeTablePageNumber"
|
:page-size="changeTablePageSize"
|
||||||
:page-size="changeTablePageSize"
|
:total="changeTableTotal"
|
||||||
:total="changeTableTotal"
|
layout="total, prev, pager, next, jumper, sizes"
|
||||||
layout="total, prev, pager, next, jumper"
|
:page-sizes="[10, 20, 50, 100, 9999]"
|
||||||
@current-change="handlePageChange"
|
popper-class="pagination-select-dropdown"
|
||||||
/>
|
@current-change="handlePageChange"
|
||||||
|
@size-change="handlePageSizeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-if="progressDetail.description" class="description-block">
|
<div v-if="progressDetail.description" class="description-block">
|
||||||
<span class="label">说明:</span>
|
<span class="label">说明:</span>
|
||||||
<span class="value">{{ detailOption }}</span>
|
<span class="value">{{ detailOption }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block-section">
|
<section class="block-section">
|
||||||
<div class="section-title">
|
<div class="section-title" @click="toggleApprovalFlow">
|
||||||
审批流程
|
审批流程
|
||||||
|
<i :class="approvalFlowCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="timelineNodes && timelineNodes.length > 0" class="approval-timeline">
|
<div v-show="!approvalFlowCollapsed" v-if="timelineNodes && timelineNodes.length > 0" class="approval-timeline">
|
||||||
<el-timeline>
|
<el-timeline>
|
||||||
<el-timeline-item
|
<el-timeline-item
|
||||||
v-for="(node, index) in timelineNodes"
|
v-for="(node, index) in timelineNodes"
|
||||||
@ -247,7 +256,7 @@
|
|||||||
</el-timeline-item>
|
</el-timeline-item>
|
||||||
</el-timeline>
|
</el-timeline>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="empty-progress">
|
<div v-show="!approvalFlowCollapsed" v-else class="empty-progress">
|
||||||
<span class="empty-text">暂无审批流程数据</span>
|
<span class="empty-text">暂无审批流程数据</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -369,6 +378,10 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
basicInfoCollapsed: true, // 基础信息是否折叠,默认关闭
|
||||||
|
detailInfoCollapsed: false, // 详细信息是否折叠,默认展开
|
||||||
|
approvalContentCollapsed: false, // 审批内容是否折叠,默认展开
|
||||||
|
approvalFlowCollapsed: true, // 审批流程是否折叠,默认关闭
|
||||||
changeTable: [],
|
changeTable: [],
|
||||||
showTopDetail: {
|
showTopDetail: {
|
||||||
processTitle: '',
|
processTitle: '',
|
||||||
@ -422,6 +435,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
changeTablePage() {
|
||||||
|
return this.changeTablePageNumber
|
||||||
|
},
|
||||||
titleText() {
|
titleText() {
|
||||||
console.log(this.engineType, 'this.engineType', this.detail, 111111)
|
console.log(this.engineType, 'this.engineType', this.detail, 111111)
|
||||||
return this.engineType === '玉柴' ? '玉柴发动机审批详情' : '竞品发动机审批详情'
|
return this.engineType === '玉柴' ? '玉柴发动机审批详情' : '竞品发动机审批详情'
|
||||||
@ -617,6 +633,18 @@ export default {
|
|||||||
// this.getApprovalChange()
|
// this.getApprovalChange()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
toggleBasicInfo() {
|
||||||
|
this.basicInfoCollapsed = !this.basicInfoCollapsed
|
||||||
|
},
|
||||||
|
toggleDetailInfo() {
|
||||||
|
this.detailInfoCollapsed = !this.detailInfoCollapsed
|
||||||
|
},
|
||||||
|
toggleApprovalContent() {
|
||||||
|
this.approvalContentCollapsed = !this.approvalContentCollapsed
|
||||||
|
},
|
||||||
|
toggleApprovalFlow() {
|
||||||
|
this.approvalFlowCollapsed = !this.approvalFlowCollapsed
|
||||||
|
},
|
||||||
canResendApproval() {
|
canResendApproval() {
|
||||||
const request = {
|
const request = {
|
||||||
...api.CHECK_DATA_CAN_RETURN,
|
...api.CHECK_DATA_CAN_RETURN,
|
||||||
@ -1253,6 +1281,11 @@ export default {
|
|||||||
// 只更新当前页显示的数据,不需要重新请求接口
|
// 只更新当前页显示的数据,不需要重新请求接口
|
||||||
this.updatePagedData()
|
this.updatePagedData()
|
||||||
},
|
},
|
||||||
|
handlePageSizeChange(size) {
|
||||||
|
this.changeTablePageSize = size
|
||||||
|
this.changeTablePageNumber = 1
|
||||||
|
this.updatePagedData()
|
||||||
|
},
|
||||||
changeTypeClass(type) {
|
changeTypeClass(type) {
|
||||||
if (type === 'create') return 'change-create'
|
if (type === 'create') return 'change-create'
|
||||||
if (type === 'delete') return 'change-delete'
|
if (type === 'delete') return 'change-delete'
|
||||||
@ -1486,6 +1519,21 @@ export default {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.collapse-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1623,8 +1671,22 @@ export default {
|
|||||||
.pagination-wrapper {
|
.pagination-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
|
::v-deep .el-pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.el-select {
|
||||||
|
.el-input {
|
||||||
|
width: 100px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modify-details-text {
|
.modify-details-text {
|
||||||
@ -1882,3 +1944,21 @@ export default {
|
|||||||
line-height: 0.85 !important;
|
line-height: 0.85 !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pagination-select-dropdown {
|
||||||
|
width: 110px !important;
|
||||||
|
min-width: 110px !important;
|
||||||
|
max-width: 110px !important;
|
||||||
|
|
||||||
|
.el-select-dropdown__wrap {
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -25,6 +25,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="!isApprovalMode && !hideOperations" class="operation">
|
<div v-if="!isApprovalMode && !hideOperations" class="operation">
|
||||||
<template v-if="isDispatchMode">
|
<template v-if="isDispatchMode">
|
||||||
|
<el-button
|
||||||
|
v-if="dispatchType !== 'update_param'"
|
||||||
|
size="small"
|
||||||
|
@click="handleBatchModifyDept"
|
||||||
|
>
|
||||||
|
批量修改部门
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="shouldShowRejectButton"
|
v-if="shouldShowRejectButton"
|
||||||
size="small"
|
size="small"
|
||||||
@ -62,12 +69,12 @@
|
|||||||
<el-button size="small" v-if="!isEditDeptMode && hasAnyEditPermission() && detail &&( detail.distributeStatus === '已完成' || detail.distributeStatus === '未分发')" @click="handleEditDept">
|
<el-button size="small" v-if="!isEditDeptMode && hasAnyEditPermission() && detail &&( detail.distributeStatus === '已完成' || detail.distributeStatus === '未分发')" @click="handleEditDept">
|
||||||
编辑部门
|
编辑部门
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<!-- <el-button
|
||||||
v-if="!isEditMode && !isEditDeptMode && hasAnyEditPermission() && detail && detail.distributeStatus === '已完成'"
|
v-if="!isEditMode && !isEditDeptMode && hasAnyEditPermission() && (detail && detail.distributeStatus === '已完成' || fromTodo)"
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleEdit">
|
@click="handleEdit">
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button> -->
|
||||||
<el-button
|
<el-button
|
||||||
v-if="!isEditMode && !isEditDeptMode && !isJustCheckMode"
|
v-if="!isEditMode && !isEditDeptMode && !isJustCheckMode"
|
||||||
size="small"
|
size="small"
|
||||||
@ -194,8 +201,11 @@
|
|||||||
<!-- 发动机基本信息表格 -->
|
<!-- 发动机基本信息表格 -->
|
||||||
<template v-for="(sectionData, sectionKey) in wholeEngineParamsData">
|
<template v-for="(sectionData, sectionKey) in wholeEngineParamsData">
|
||||||
<div v-if="isWholeEngineParamsSelected" class="section" :key="sectionKey">
|
<div v-if="isWholeEngineParamsSelected" class="section" :key="sectionKey">
|
||||||
<div class="section-title">{{ sectionKey }}</div>
|
<div class="section-title" @click="detailInfoCollapsed = !detailInfoCollapsed" style="cursor: pointer;">
|
||||||
<div class="grid whole-engine-grid">
|
<span>{{ sectionKey }}</span>
|
||||||
|
<i :class="detailInfoCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
|
||||||
|
</div>
|
||||||
|
<div class="grid whole-engine-grid" v-show="!detailInfoCollapsed">
|
||||||
<div
|
<div
|
||||||
class="grid-header whole-engine-header"
|
class="grid-header whole-engine-header"
|
||||||
:class="{ 'without-parameter-source': isCompetitiveEngineEntry }"
|
:class="{ 'without-parameter-source': isCompetitiveEngineEntry }"
|
||||||
@ -226,6 +236,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- 子系统参数表格 -->
|
<!-- 子系统参数表格 -->
|
||||||
|
<div class="params-control" style="margin-bottom: 10px; text-align: right;" v-if="!isWholeEngineParamsSelected">
|
||||||
|
<el-checkbox v-model="showAllParams">全部显示(不分页)</el-checkbox>
|
||||||
|
</div>
|
||||||
<template v-for="(sectionData, sectionKey) in display">
|
<template v-for="(sectionData, sectionKey) in display">
|
||||||
<div class="section" v-if="shouldShowSection(sectionKey)" :key="sectionKey">
|
<div class="section" v-if="shouldShowSection(sectionKey)" :key="sectionKey">
|
||||||
<div class="section-title">{{ formatSectionTitle(sectionKey, sectionData) }}</div>
|
<div class="section-title">{{ formatSectionTitle(sectionKey, sectionData) }}</div>
|
||||||
@ -376,10 +389,11 @@
|
|||||||
<div v-if="isApprovalMode" class="page-approval-content">
|
<div v-if="isApprovalMode" class="page-approval-content">
|
||||||
<!-- 基础信息 -->
|
<!-- 基础信息 -->
|
||||||
<section v-if="detail" class="block-section">
|
<section v-if="detail" class="block-section">
|
||||||
<div class="section-title">
|
<div class="section-title" @click="basicInfoCollapsed = !basicInfoCollapsed" style="cursor: pointer;">
|
||||||
基础信息
|
<span>基础信息</span>
|
||||||
|
<i :class="basicInfoCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-grid">
|
<div class="info-grid" v-show="!basicInfoCollapsed">
|
||||||
<!-- 流程主题单独一行 -->
|
<!-- 流程主题单独一行 -->
|
||||||
<div class="info-item-full">
|
<div class="info-item-full">
|
||||||
<span class="label">流程主题 <span class="required-mark">*</span></span>
|
<span class="label">流程主题 <span class="required-mark">*</span></span>
|
||||||
@ -476,10 +490,11 @@
|
|||||||
|
|
||||||
<!-- 审批环节 -->
|
<!-- 审批环节 -->
|
||||||
<div class="approval-workflow">
|
<div class="approval-workflow">
|
||||||
<div class="workflow-title">
|
<div class="workflow-title" @click="approvalWorkflowCollapsed = !approvalWorkflowCollapsed" style="cursor: pointer;">
|
||||||
审批环节
|
<span>审批环节</span>
|
||||||
|
<i :class="approvalWorkflowCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="workflow-table">
|
<div class="workflow-table" v-show="!approvalWorkflowCollapsed">
|
||||||
<table class="workflow-table-content">
|
<table class="workflow-table-content">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -558,10 +573,147 @@
|
|||||||
:resolve-department-id="resolveDepartmentId"
|
:resolve-department-id="resolveDepartmentId"
|
||||||
:project-parts-name="treeFirstLevelPartsName"
|
:project-parts-name="treeFirstLevelPartsName"
|
||||||
:tree-subsystem-names="treeSubsystemNames"
|
:tree-subsystem-names="treeSubsystemNames"
|
||||||
|
:dispatch-param-draft-cache="dispatchParamDraftCache"
|
||||||
@confirm="handleBatchModifyConfirm"
|
@confirm="handleBatchModifyConfirm"
|
||||||
@refresh-responsible-persons="loadResponsiblePersons"
|
@refresh-responsible-persons="loadResponsiblePersons"
|
||||||
|
@refresh-department="handleRefreshDepartment"
|
||||||
|
@update-draft-cache="handleUpdateDraftCache"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 修改部门弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="修改部门"
|
||||||
|
:visible.sync="batchModifyDeptDialogVisible"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
@close="handleBatchModifyDeptDialogClose"
|
||||||
|
>
|
||||||
|
<el-form ref="batchModifyDeptForm" :model="batchModifyDeptFormData" label-width="110px">
|
||||||
|
<el-form-item label="原部门:">
|
||||||
|
<el-input
|
||||||
|
v-model="batchModifyDeptFormData.originalDept"
|
||||||
|
placeholder="请选择原部门"
|
||||||
|
readonly
|
||||||
|
style="width: 100%"
|
||||||
|
@click.native="handleSelectOriginalDept"
|
||||||
|
>
|
||||||
|
<el-button slot="append" icon="el-icon-search" @click="handleSelectOriginalDept"></el-button>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门:">
|
||||||
|
<el-input
|
||||||
|
v-model="batchModifyDeptFormData.targetDept"
|
||||||
|
placeholder="请选择部门"
|
||||||
|
readonly
|
||||||
|
style="width: 100%"
|
||||||
|
@click.native="handleSelectTargetDept"
|
||||||
|
>
|
||||||
|
<el-button slot="append" icon="el-icon-search" @click="handleSelectTargetDept"></el-button>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleBatchModifyDeptDialogClose">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:loading="batchModifyDeptSubmitting"
|
||||||
|
:disabled="!batchModifyDeptFormData.originalDept || !batchModifyDeptFormData.targetDept"
|
||||||
|
@click="handleBatchModifyDeptConfirm"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 原填写部门选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="选择原填写部门"
|
||||||
|
:visible.sync="originalDeptDialogVisible"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
@close="handleOriginalDeptDialogClose"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="originalDeptTreeFilterText"
|
||||||
|
size="small"
|
||||||
|
placeholder="请输入部门名称进行搜索"
|
||||||
|
clearable
|
||||||
|
class="department-tree-search"
|
||||||
|
>
|
||||||
|
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||||
|
</el-input>
|
||||||
|
<el-tree
|
||||||
|
ref="originalDeptTree"
|
||||||
|
:data="departmentList"
|
||||||
|
:props="{ children: 'children', label: 'name' }"
|
||||||
|
node-key="id"
|
||||||
|
:filter-node-method="filterDepartmentNode"
|
||||||
|
highlight-current
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
class="department-tree"
|
||||||
|
@node-click="handleOriginalDeptNodeClick"
|
||||||
|
/>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleOriginalDeptDialogClose">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!selectedOriginalDeptId"
|
||||||
|
@click="handleOriginalDeptDialogConfirm"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 填写部门选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="选择填写部门"
|
||||||
|
:visible.sync="targetDeptDialogVisible"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
@close="handleTargetDeptDialogClose"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="targetDeptTreeFilterText"
|
||||||
|
size="small"
|
||||||
|
placeholder="请输入部门名称进行搜索"
|
||||||
|
clearable
|
||||||
|
class="department-tree-search"
|
||||||
|
>
|
||||||
|
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||||
|
</el-input>
|
||||||
|
<el-tree
|
||||||
|
ref="targetDeptTree"
|
||||||
|
:data="departmentList"
|
||||||
|
:props="{ children: 'children', label: 'name' }"
|
||||||
|
node-key="id"
|
||||||
|
:filter-node-method="filterDepartmentNode"
|
||||||
|
highlight-current
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
class="department-tree"
|
||||||
|
@node-click="handleTargetDeptNodeClick"
|
||||||
|
/>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleTargetDeptDialogClose">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!selectedTargetDeptId"
|
||||||
|
@click="handleTargetDeptDialogConfirm"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 竞品发动机:修改全部填写人/责任人(仅选人,不触发修改责任人接口) -->
|
<!-- 竞品发动机:修改全部填写人/责任人(仅选人,不触发修改责任人接口) -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="dispatchType === 'update_param' ? '修改全部填写人' : '修改全部责任人'"
|
:title="dispatchType === 'update_param' ? '修改全部填写人' : '修改全部责任人'"
|
||||||
@ -611,76 +763,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 批量修改部门弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
title="批量修改部门"
|
|
||||||
:visible.sync="batchModifyDeptDialogVisible"
|
|
||||||
width="600px"
|
|
||||||
append-to-body
|
|
||||||
@close="handleBatchModifyDeptDialogClose"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="batchModifyDeptForm"
|
|
||||||
:model="batchModifyDeptFormData"
|
|
||||||
:rules="batchModifyDeptFormRules"
|
|
||||||
label-width="120px"
|
|
||||||
>
|
|
||||||
<el-form-item label="子系统:" prop="subsystem">
|
|
||||||
<el-select
|
|
||||||
v-model="batchModifyDeptFormData.subsystem"
|
|
||||||
placeholder="请选择子系统"
|
|
||||||
clearable
|
|
||||||
style="width: 100%"
|
|
||||||
@change="handleBatchModifyDeptSubsystemChange"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in batchModifyDeptSubsystemList"
|
|
||||||
:key="item"
|
|
||||||
:label="item"
|
|
||||||
:value="item"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="零部件名称:" prop="partsName">
|
|
||||||
<el-select
|
|
||||||
v-model="batchModifyDeptFormData.partsName"
|
|
||||||
placeholder="请选择零部件名称"
|
|
||||||
clearable
|
|
||||||
multiple
|
|
||||||
style="width: 100%"
|
|
||||||
:disabled="!batchModifyDeptFormData.subsystem"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in batchModifyDeptPartsNameList"
|
|
||||||
:key="item"
|
|
||||||
:label="item"
|
|
||||||
:value="item"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="部门:" prop="department">
|
|
||||||
<el-select
|
|
||||||
v-model="batchModifyDeptFormData.department"
|
|
||||||
placeholder="请选择部门"
|
|
||||||
clearable
|
|
||||||
filterable
|
|
||||||
style="width: 100%"
|
|
||||||
:filter-method="handleBatchModifyDeptRemoteSearch"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="dept in filteredBatchModifyDeptOptions"
|
|
||||||
:key="dept.id"
|
|
||||||
:value="dept.name"
|
|
||||||
:label="dept.name"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="handleBatchModifyDeptDialogClose">取消</el-button>
|
|
||||||
<el-button type="primary" :loading="batchModifyDeptSubmitting" @click="handleBatchModifyDeptConfirm">确定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -810,6 +893,24 @@ export default {
|
|||||||
},
|
},
|
||||||
replaceAllPersonUserOptions: [],
|
replaceAllPersonUserOptions: [],
|
||||||
replaceAllPersonUserLoading: false,
|
replaceAllPersonUserLoading: false,
|
||||||
|
// 修改部门相关
|
||||||
|
batchModifyDeptDialogVisible: false,
|
||||||
|
batchModifyDeptSubmitting: false,
|
||||||
|
batchModifyDeptFormData: {
|
||||||
|
|
||||||
|
originalDept: '',
|
||||||
|
originalDeptId: '',
|
||||||
|
targetDept: '',
|
||||||
|
targetDeptId: ''
|
||||||
|
},
|
||||||
|
originalDeptDialogVisible: false,
|
||||||
|
originalDeptTreeFilterText: '',
|
||||||
|
selectedOriginalDeptId: '',
|
||||||
|
selectedOriginalDeptName: '',
|
||||||
|
targetDeptDialogVisible: false,
|
||||||
|
targetDeptTreeFilterText: '',
|
||||||
|
selectedTargetDeptId: '',
|
||||||
|
selectedTargetDeptName: '',
|
||||||
// 树节点ID到右侧数据部分的映射
|
// 树节点ID到右侧数据部分的映射
|
||||||
versions: [],
|
versions: [],
|
||||||
treeData: [],
|
treeData: [],
|
||||||
@ -817,6 +918,10 @@ export default {
|
|||||||
currentEngineModelID: '', // 当前机型ID
|
currentEngineModelID: '', // 当前机型ID
|
||||||
versionData: {},
|
versionData: {},
|
||||||
changeData: [], // 存储修改的数据项
|
changeData: [], // 存储修改的数据项
|
||||||
|
basicInfoCollapsed: false, // 基础信息是否折叠
|
||||||
|
detailInfoCollapsed: false, // 详细信息是否折叠
|
||||||
|
approvalWorkflowCollapsed: true, // 审批环节是否折叠(默认折叠)
|
||||||
|
showAllParams: false, // 是否显示全部参数(不分页)
|
||||||
importing: false, // 导入中状态
|
importing: false, // 导入中状态
|
||||||
isApprovalMode: false, // 发起审批模式状态
|
isApprovalMode: false, // 发起审批模式状态
|
||||||
engineDetailInfo: null, // 机型详情信息(包含 modelName 和 projectNumber)
|
engineDetailInfo: null, // 机型详情信息(包含 modelName 和 projectNumber)
|
||||||
@ -880,6 +985,16 @@ export default {
|
|||||||
console.log('data', data)
|
console.log('data', data)
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
// 显示的参数数据(支持全部显示或分页)
|
||||||
|
displayParams() {
|
||||||
|
const data = this.display
|
||||||
|
if (this.showAllParams) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
// 如果不分页,直接返回所有数据
|
||||||
|
// 这里可以根据需要添加分页逻辑
|
||||||
|
return data
|
||||||
|
},
|
||||||
currentVersionLabel() {
|
currentVersionLabel() {
|
||||||
const version = this.versions.find((v) => v.id === this.currentVersionId)
|
const version = this.versions.find((v) => v.id === this.currentVersionId)
|
||||||
return version ? version.label : 'V1'
|
return version ? version.label : 'V1'
|
||||||
@ -1016,6 +1131,22 @@ export default {
|
|||||||
})
|
})
|
||||||
return names
|
return names
|
||||||
},
|
},
|
||||||
|
// 子系统列表(用于修改部门弹窗)
|
||||||
|
subsystemList() {
|
||||||
|
const currentData = this.versionData[this.currentVersionId] || {}
|
||||||
|
const subsystemSet = new Set()
|
||||||
|
|
||||||
|
Object.keys(currentData).forEach((partsName) => {
|
||||||
|
const params = currentData[partsName] || []
|
||||||
|
params.forEach((param) => {
|
||||||
|
if (param.subsystemName) {
|
||||||
|
subsystemSet.add(param.subsystemName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Array.from(subsystemSet).sort()
|
||||||
|
},
|
||||||
// 判断是否是查看模式(justCheck)
|
// 判断是否是查看模式(justCheck)
|
||||||
isJustCheckMode() {
|
isJustCheckMode() {
|
||||||
return this.dispatchType === 'justCheck'
|
return this.dispatchType === 'justCheck'
|
||||||
@ -1179,10 +1310,25 @@ export default {
|
|||||||
},
|
},
|
||||||
// 非填写人待办是否展示头部操作区(编辑、退回等)
|
// 非填写人待办是否展示头部操作区(编辑、退回等)
|
||||||
canShowTodoHeaderOperations() {
|
canShowTodoHeaderOperations() {
|
||||||
|
console.log('canShowTodoHeaderOperations - isFillerTodoEntry:', this.isFillerTodoEntry)
|
||||||
|
console.log('canShowTodoHeaderOperations - fromTodo:', this.fromTodo)
|
||||||
|
console.log('canShowTodoHeaderOperations - detail:', this.detail)
|
||||||
|
console.log('canShowTodoHeaderOperations - distributeStatus:', this.detail && this.detail.distributeStatus)
|
||||||
|
|
||||||
if (this.isFillerTodoEntry) {
|
if (this.isFillerTodoEntry) {
|
||||||
|
console.log('canShowTodoHeaderOperations - 返回 true (isFillerTodoEntry)')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return !this.detail || this.detail.distributeStatus !== '已完成'
|
// 从待办进入时,始终显示操作区(包括被退回的情况)
|
||||||
|
if (this.fromTodo) {
|
||||||
|
console.log('canShowTodoHeaderOperations - 返回 true (fromTodo)')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// 使用传统访问方式确保浏览器兼容性
|
||||||
|
const distributeStatus = this.detail && this.detail.distributeStatus
|
||||||
|
const result = !this.detail || distributeStatus !== '已完成'
|
||||||
|
console.log('canShowTodoHeaderOperations - 返回:', result)
|
||||||
|
return result
|
||||||
},
|
},
|
||||||
// 判断是否应该显示"退回"按钮(责任人、填写人待办均可用)
|
// 判断是否应该显示"退回"按钮(责任人、填写人待办均可用)
|
||||||
shouldShowRejectButton() {
|
shouldShowRejectButton() {
|
||||||
@ -1315,6 +1461,20 @@ export default {
|
|||||||
this.loadResponsiblePersons()
|
this.loadResponsiblePersons()
|
||||||
this.loadFillerPersons()
|
this.loadFillerPersons()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
originalDeptTreeFilterText(val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.originalDeptTree) {
|
||||||
|
this.$refs.originalDeptTree.filter(val)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
targetDeptTreeFilterText(val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.targetDeptTree) {
|
||||||
|
this.$refs.targetDeptTree.filter(val)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -1735,11 +1895,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 检查是否有任意子系统的编辑权限(与参数编辑权限使用相同的逻辑)
|
// 检查是否有任意子系统的编辑权限(与参数编辑权限使用相同的逻辑)
|
||||||
hasAnyEditPermission() {
|
hasAnyEditPermission() {
|
||||||
// 从待办进入且类型为「数据维护」:直接视为具备编辑权限(用于展示编辑等按钮)
|
// 从待办进入且类型为「数据维护」或「数据拒绝」:直接视为具备编辑权限(用于展示编辑等按钮)
|
||||||
|
const dataTypeStr = String(this.detail.dataType || '')
|
||||||
|
console.log(dataTypeStr)
|
||||||
if (
|
if (
|
||||||
this.fromTodo &&
|
this.fromTodo &&
|
||||||
this.detail &&
|
this.detail &&
|
||||||
String(this.detail.dataType || '') === '数据维护'
|
(dataTypeStr === '数据维护' || dataTypeStr === '数据拒绝')
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -1765,7 +1927,7 @@ export default {
|
|||||||
const hasGlobalEdit = permissionData.some((perm) => {
|
const hasGlobalEdit = permissionData.some((perm) => {
|
||||||
const permissionPath = perm.permissionPath || ''
|
const permissionPath = perm.permissionPath || ''
|
||||||
const parameterPer = perm.parameterPer || ''
|
const parameterPer = perm.parameterPer || ''
|
||||||
// 精准匹配:permissionPath 等于 engineTypePath 且 parameterPer 为"编辑"
|
// 精确匹配:permissionPath 等于 engineTypePath 且 parameterPer 为"编辑"
|
||||||
return permissionPath === engineTypePath && parameterPer === '编辑'
|
return permissionPath === engineTypePath && parameterPer === '编辑'
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1782,6 +1944,7 @@ export default {
|
|||||||
return parameterPer === '编辑' && permissionPath.startsWith(engineTypePath + '/')
|
return parameterPer === '编辑' && permissionPath.startsWith(engineTypePath + '/')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
return hasAnyEdit
|
return hasAnyEdit
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('检查编辑权限失败:', err)
|
console.error('检查编辑权限失败:', err)
|
||||||
@ -1797,30 +1960,34 @@ export default {
|
|||||||
return (person.partsName || '') === treePartsName
|
return (person.partsName || '') === treePartsName
|
||||||
},
|
},
|
||||||
// 根据子系统、部门匹配责任人
|
// 根据子系统、部门匹配责任人
|
||||||
|
// 根据子系统、部门匹配责任人(取消子系统匹配,只匹配部门)
|
||||||
isResponsiblePersonSubsystemDeptMatch(person, subsystemName, department) {
|
isResponsiblePersonSubsystemDeptMatch(person, subsystemName, department) {
|
||||||
if (!person) {
|
if (!person) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let subsystemMatch = false
|
|
||||||
if (subsystemName && person.subsystem) {
|
|
||||||
const personSubsystems = person.subsystem.split(',').map((s) => s.trim())
|
|
||||||
subsystemMatch = personSubsystems.includes(subsystemName)
|
|
||||||
} else if (!subsystemName && !person.subsystem) {
|
|
||||||
subsystemMatch = true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 取消子系统匹配,只匹配部门
|
||||||
let departmentMatch = false
|
let departmentMatch = false
|
||||||
if (department && person.department) {
|
if (department && person.department) {
|
||||||
const normalizedParamDept = department.replace(/·/g, '-')
|
const normalizedParamDept = department.replace(/·/g, '-')
|
||||||
const normalizedPersonDept = person.department.replace(/·/g, '-')
|
const normalizedPersonDept = person.department.replace(/·/g, '-')
|
||||||
departmentMatch =
|
|
||||||
|
// 精确匹配或前缀匹配
|
||||||
|
const exactMatch =
|
||||||
normalizedPersonDept === normalizedParamDept ||
|
normalizedPersonDept === normalizedParamDept ||
|
||||||
normalizedPersonDept.startsWith(normalizedParamDept + '-')
|
normalizedPersonDept.startsWith(normalizedParamDept + '-')
|
||||||
|
|
||||||
|
// 部门别名匹配:如果参数部门或责任人部门是别名关系,也视为匹配
|
||||||
|
const aliasMatch =
|
||||||
|
this.isZQOrZZPowerPlatformDept(department) &&
|
||||||
|
this.isZQOrZZPowerPlatformDept(person.department)
|
||||||
|
|
||||||
|
departmentMatch = exactMatch || aliasMatch
|
||||||
} else if (!department && !person.department) {
|
} else if (!department && !person.department) {
|
||||||
departmentMatch = true
|
departmentMatch = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return subsystemMatch && departmentMatch
|
return departmentMatch
|
||||||
},
|
},
|
||||||
// 加载责任人列表(从 GET_MANAGER_DATA 接口获取)
|
// 加载责任人列表(从 GET_MANAGER_DATA 接口获取)
|
||||||
loadResponsiblePersons() {
|
loadResponsiblePersons() {
|
||||||
@ -2162,6 +2329,12 @@ export default {
|
|||||||
}
|
}
|
||||||
this.saveDispatchParamDraft(row)
|
this.saveDispatchParamDraft(row)
|
||||||
},
|
},
|
||||||
|
// 处理批量修改填写人弹窗更新draft缓存
|
||||||
|
handleUpdateDraftCache(draftKey, draft) {
|
||||||
|
if (draftKey && draft) {
|
||||||
|
this.$set(this.dispatchParamDraftCache, draftKey, draft)
|
||||||
|
}
|
||||||
|
},
|
||||||
// 根据部门过滤人员列表(保留以兼容旧代码)
|
// 根据部门过滤人员列表(保留以兼容旧代码)
|
||||||
getFilteredPersonsByDepartment(department) {
|
getFilteredPersonsByDepartment(department) {
|
||||||
if (!department) {
|
if (!department) {
|
||||||
@ -2990,6 +3163,227 @@ export default {
|
|||||||
// 直接打开弹窗,弹窗内部会处理数据加载
|
// 直接打开弹窗,弹窗内部会处理数据加载
|
||||||
this.$refs.batchModifyResponsibleModal.showModal()
|
this.$refs.batchModifyResponsibleModal.showModal()
|
||||||
},
|
},
|
||||||
|
// 修改部门弹窗关闭
|
||||||
|
handleBatchModifyDeptDialogClose() {
|
||||||
|
this.batchModifyDeptDialogVisible = false
|
||||||
|
this.batchModifyDeptFormData = {
|
||||||
|
|
||||||
|
originalDept: '',
|
||||||
|
originalDeptId: '',
|
||||||
|
targetDept: '',
|
||||||
|
targetDeptId: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 修改部门确认
|
||||||
|
handleBatchModifyDeptConfirm() {
|
||||||
|
if (!this.batchModifyDeptFormData.originalDept || !this.batchModifyDeptFormData.targetDept) {
|
||||||
|
this.$message.warning('请选择原部门和部门')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.batchModifyDeptFormData.originalDept === this.batchModifyDeptFormData.targetDept) {
|
||||||
|
this.$message.warning('原部门和部门不能相同')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 versionData 中找出需要更新的参数(不限制子系统,在所有参数中查找)
|
||||||
|
const currentVersionData = this.versionData[this.currentVersionId] || {}
|
||||||
|
|
||||||
|
// 收集当前数据中存在的部门列表
|
||||||
|
const existingDepts = new Set()
|
||||||
|
Object.keys(currentVersionData).forEach((partsName) => {
|
||||||
|
const params = currentVersionData[partsName] || []
|
||||||
|
params.forEach((param) => {
|
||||||
|
if (param.department) {
|
||||||
|
existingDepts.add(param.department)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const existingDeptsArray = Array.from(existingDepts)
|
||||||
|
|
||||||
|
// 先检查原部门是否精确存在于数据中
|
||||||
|
const originalDeptExists = existingDeptsArray.includes(this.batchModifyDeptFormData.originalDept)
|
||||||
|
|
||||||
|
if (!originalDeptExists) {
|
||||||
|
// 原部门不存在,提示用户
|
||||||
|
const message = `原部门【${this.batchModifyDeptFormData.originalDept}】不存在于当前数据中。\n当前存在的部门:${existingDeptsArray.join('、')}`
|
||||||
|
this.$message.warning(message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原部门存在,查找需要更新的参数
|
||||||
|
const itemsToUpdate = []
|
||||||
|
|
||||||
|
Object.keys(currentVersionData).forEach((partsName) => {
|
||||||
|
const params = currentVersionData[partsName] || []
|
||||||
|
params.forEach((param) => {
|
||||||
|
// 检查部门是否匹配(使用部门别名匹配)
|
||||||
|
if (this.isDepartmentMatched(param.department, this.batchModifyDeptFormData.originalDept)) {
|
||||||
|
if (param.id) {
|
||||||
|
itemsToUpdate.push({
|
||||||
|
id: param.id,
|
||||||
|
department: this.batchModifyDeptFormData.targetDept
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 如果没有找到匹配的参数,提示用户
|
||||||
|
if (itemsToUpdate.length === 0) {
|
||||||
|
this.$message.warning('未找到匹配的参数数据')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用后端接口批量更新部门
|
||||||
|
const request = {
|
||||||
|
...api.BATCH_UPDATE_DEPARTMENT,
|
||||||
|
params: {
|
||||||
|
items: itemsToUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.batchModifyDeptSubmitting = true
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
// 更新前端显示的部门,并同时更新责任人
|
||||||
|
Object.keys(currentVersionData).forEach((partsName) => {
|
||||||
|
const params = currentVersionData[partsName] || []
|
||||||
|
params.forEach((param, index) => {
|
||||||
|
if (this.isDepartmentMatched(param.department, this.batchModifyDeptFormData.originalDept)) {
|
||||||
|
// 更新部门
|
||||||
|
param.department = this.batchModifyDeptFormData.targetDept
|
||||||
|
|
||||||
|
// 根据新部门匹配责任人
|
||||||
|
const matchedPerson = this.responsiblePersons.find((person) => {
|
||||||
|
return this.isResponsiblePersonSubsystemDeptMatch(person, param.subsystemName, param.department)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (matchedPerson) {
|
||||||
|
// 更新责任人信息
|
||||||
|
param.resPersonId = matchedPerson.userId || matchedPerson.id || ''
|
||||||
|
param.owner = matchedPerson.userName || matchedPerson.username || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.batchModifyDeptSubmitting = false
|
||||||
|
this.batchModifyDeptDialogVisible = false
|
||||||
|
this.$message.success(`成功更新 ${itemsToUpdate.length} 个参数的部门`)
|
||||||
|
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('批量更新部门失败:', err)
|
||||||
|
this.$message.error('批量更新部门失败,请重试')
|
||||||
|
this.batchModifyDeptSubmitting = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 部门名称是否匹配(支持部门别名)
|
||||||
|
isDepartmentMatched(deptA, deptB) {
|
||||||
|
if (!deptA || !deptB) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 标准化部门名称
|
||||||
|
const normalizeDept = (dept) => {
|
||||||
|
if (!dept) return ''
|
||||||
|
return dept.replace(/·/g, '-').trim()
|
||||||
|
}
|
||||||
|
const normalizedA = normalizeDept(deptA)
|
||||||
|
const normalizedB = normalizeDept(deptB)
|
||||||
|
|
||||||
|
// 直接匹配
|
||||||
|
if (normalizedA === normalizedB) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 部门别名匹配:中轻、中重动力平台、平台部、中轻动力平台部、中重动力平台部 都视为同一部门
|
||||||
|
const aliasGroups = [
|
||||||
|
['中轻', '中重动力平台', '平台部', '中轻动力平台部', '中重动力平台部']
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const group of aliasGroups) {
|
||||||
|
if (group.some(alias => normalizedA.includes(alias)) && group.some(alias => normalizedB.includes(alias))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
// 选择原填写部门
|
||||||
|
handleSelectOriginalDept() {
|
||||||
|
this.originalDeptDialogVisible = true
|
||||||
|
this.selectedOriginalDeptId = this.batchModifyDeptFormData.originalDeptId || ''
|
||||||
|
this.selectedOriginalDeptName = this.batchModifyDeptFormData.originalDept || ''
|
||||||
|
this.originalDeptTreeFilterText = ''
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.originalDeptTree && this.selectedOriginalDeptId) {
|
||||||
|
this.$refs.originalDeptTree.setCurrentKey(this.selectedOriginalDeptId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 关闭原填写部门选择弹窗
|
||||||
|
handleOriginalDeptDialogClose() {
|
||||||
|
this.originalDeptDialogVisible = false
|
||||||
|
this.selectedOriginalDeptId = ''
|
||||||
|
this.selectedOriginalDeptName = ''
|
||||||
|
},
|
||||||
|
// 原填写部门树节点点击
|
||||||
|
handleOriginalDeptNodeClick(data) {
|
||||||
|
this.selectedOriginalDeptId = data.id
|
||||||
|
this.selectedOriginalDeptName = data.name
|
||||||
|
},
|
||||||
|
// 确认选择原填写部门
|
||||||
|
handleOriginalDeptDialogConfirm() {
|
||||||
|
if (!this.selectedOriginalDeptId) {
|
||||||
|
this.$message.warning('请选择部门')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.batchModifyDeptFormData.originalDept = this.selectedOriginalDeptName
|
||||||
|
this.batchModifyDeptFormData.originalDeptId = this.selectedOriginalDeptId
|
||||||
|
this.originalDeptDialogVisible = false
|
||||||
|
},
|
||||||
|
// 选择填写部门
|
||||||
|
handleSelectTargetDept() {
|
||||||
|
this.targetDeptDialogVisible = true
|
||||||
|
this.selectedTargetDeptId = this.batchModifyDeptFormData.targetDeptId || ''
|
||||||
|
this.selectedTargetDeptName = this.batchModifyDeptFormData.targetDept || ''
|
||||||
|
this.targetDeptTreeFilterText = ''
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.targetDeptTree && this.selectedTargetDeptId) {
|
||||||
|
this.$refs.targetDeptTree.setCurrentKey(this.selectedTargetDeptId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 关闭填写部门选择弹窗
|
||||||
|
handleTargetDeptDialogClose() {
|
||||||
|
this.targetDeptDialogVisible = false
|
||||||
|
this.selectedTargetDeptId = ''
|
||||||
|
this.selectedTargetDeptName = ''
|
||||||
|
},
|
||||||
|
// 填写部门树节点点击
|
||||||
|
handleTargetDeptNodeClick(data) {
|
||||||
|
this.selectedTargetDeptId = data.id
|
||||||
|
this.selectedTargetDeptName = data.name
|
||||||
|
},
|
||||||
|
// 确认选择填写部门
|
||||||
|
handleTargetDeptDialogConfirm() {
|
||||||
|
if (!this.selectedTargetDeptId) {
|
||||||
|
this.$message.warning('请选择部门')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.batchModifyDeptFormData.targetDept = this.selectedTargetDeptName
|
||||||
|
this.batchModifyDeptFormData.targetDeptId = this.selectedTargetDeptId
|
||||||
|
this.targetDeptDialogVisible = false
|
||||||
|
},
|
||||||
|
// 刷新部门数据(部门调转后)
|
||||||
|
handleRefreshDepartment() {
|
||||||
|
// 重新加载树数据以刷新部门显示
|
||||||
|
if (this.checkedKeys && this.checkedKeys.length > 0) {
|
||||||
|
this.loadTreeData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 竞品发动机:修改全部填写人/责任人(仅选人,不触发修改责任人接口)
|
// 竞品发动机:修改全部填写人/责任人(仅选人,不触发修改责任人接口)
|
||||||
handleReplaceAllPerson() {
|
handleReplaceAllPerson() {
|
||||||
this.replaceAllPersonDialogVisible = true
|
this.replaceAllPersonDialogVisible = true
|
||||||
@ -3223,10 +3617,22 @@ export default {
|
|||||||
const subsystemMatched = selectedSubsystems.some((name) =>
|
const subsystemMatched = selectedSubsystems.some((name) =>
|
||||||
this.isSubsystemNameMatch(param.subsystemName, name)
|
this.isSubsystemNameMatch(param.subsystemName, name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 检查零部件名称是否匹配(处理 "/" 的特殊情况)
|
||||||
|
let partsNameMatched = false
|
||||||
|
if (paramPartsName === '/') {
|
||||||
|
// 对于 "/",需要检查显示名称是否在 partsName 中
|
||||||
|
const displayName = `${param.subsystemName} - /`
|
||||||
|
partsNameMatched = partsName.includes(displayName)
|
||||||
|
} else {
|
||||||
|
// 非 "/",直接检查
|
||||||
|
partsNameMatched = partsName.includes(paramPartsName)
|
||||||
|
}
|
||||||
|
|
||||||
// 已分发的填写人不能修改(isDistributedFilled === 1)
|
// 已分发的填写人不能修改(isDistributedFilled === 1)
|
||||||
if (
|
if (
|
||||||
subsystemMatched &&
|
subsystemMatched &&
|
||||||
partsName.includes(paramPartsName) &&
|
partsNameMatched &&
|
||||||
param.isDistributedFilled !== 1
|
param.isDistributedFilled !== 1
|
||||||
) {
|
) {
|
||||||
// 更新填写人信息
|
// 更新填写人信息
|
||||||
@ -3390,6 +3796,23 @@ export default {
|
|||||||
fieldValue = currentParam.resPersonId || ''
|
fieldValue = currentParam.resPersonId || ''
|
||||||
if (fieldValue) {
|
if (fieldValue) {
|
||||||
shouldDispatch = true
|
shouldDispatch = true
|
||||||
|
// 检查责任人部门与参数部门是否匹配(支持别名)
|
||||||
|
const responsiblePerson = this.responsiblePersons.find(p => p.userId === fieldValue)
|
||||||
|
if (responsiblePerson && currentParam.department) {
|
||||||
|
const paramDept = this.formatDepartmentDisplay(currentParam.department)
|
||||||
|
const personDept = this.formatDepartmentDisplay(responsiblePerson.department || '')
|
||||||
|
// 如果责任人部门与参数部门不匹配,检查是否为别名关系
|
||||||
|
if (paramDept !== personDept) {
|
||||||
|
// 中轻/中重动力平台别名匹配
|
||||||
|
const isAliasMatch =
|
||||||
|
(this.isZQOrZZPowerPlatformDept(paramDept) && this.isZQOrZZPowerPlatformDept(personDept)) ||
|
||||||
|
(this.isZQOrZZPowerPlatformDept(currentParam.department) && this.isZQOrZZPowerPlatformDept(responsiblePerson.department || ''))
|
||||||
|
if (!isAliasMatch) {
|
||||||
|
// 部门不匹配且不是别名关系,跳过分发
|
||||||
|
shouldDispatch = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3427,6 +3850,7 @@ export default {
|
|||||||
|
|
||||||
if (dispatchData.length === 0) {
|
if (dispatchData.length === 0) {
|
||||||
const fieldName = isUpdateParamMode ? '填写人' : '责任人'
|
const fieldName = isUpdateParamMode ? '填写人' : '责任人'
|
||||||
|
this.dispatchLoading = false
|
||||||
this.$message({
|
this.$message({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: `没有${fieldName}的数据需要分发`
|
message: `没有${fieldName}的数据需要分发`
|
||||||
@ -4537,7 +4961,13 @@ export default {
|
|||||||
const paramData = {
|
const paramData = {
|
||||||
parameterName: parameterName,
|
parameterName: parameterName,
|
||||||
partsName: partsName,
|
partsName: partsName,
|
||||||
parameterValue: item.parameterValue || item.value || '', // 如果接口返回中没有这个字段,默认为空
|
parameterValue: item.parameterValue !== undefined && item.parameterValue !== null && item.parameterValue !== ''
|
||||||
|
? item.parameterValue
|
||||||
|
: (item.value !== undefined && item.value !== null && item.value !== ''
|
||||||
|
? item.value
|
||||||
|
: (item.minorVersion !== undefined && item.minorVersion !== null && item.minorVersion !== ''
|
||||||
|
? item.minorVersion
|
||||||
|
: '')),
|
||||||
parameterSource: item.parameterSource || '', // 参数计划来源:直接使用 GET_ENGINE_DETAIL 返回字段
|
parameterSource: item.parameterSource || '', // 参数计划来源:直接使用 GET_ENGINE_DETAIL 返回字段
|
||||||
unit: item.unit || '-',
|
unit: item.unit || '-',
|
||||||
department: department,
|
department: department,
|
||||||
@ -4558,6 +4988,8 @@ export default {
|
|||||||
isDistributedFilled: item.isDistributedFilled || 0 // 是否已分发填写人(1表示已分发,0表示未分发)
|
isDistributedFilled: item.isDistributedFilled || 0 // 是否已分发填写人(1表示已分发,0表示未分发)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const mergedParamData = this.applyDispatchParamDraft(paramData)
|
const mergedParamData = this.applyDispatchParamDraft(paramData)
|
||||||
|
|
||||||
// 如果存在 filler 对象且有 filledByUserId,将填写人信息添加到 fillerUserOptions 中
|
// 如果存在 filler 对象且有 filledByUserId,将填写人信息添加到 fillerUserOptions 中
|
||||||
@ -5476,14 +5908,21 @@ export default {
|
|||||||
// selectedIds 是选中的 id 数组,格式: ['id1', 'id2', ...]
|
// selectedIds 是选中的 id 数组,格式: ['id1', 'id2', ...]
|
||||||
// v-model 已经自动更新了 step.handlers 为 id 数组
|
// v-model 已经自动更新了 step.handlers 为 id 数组
|
||||||
},
|
},
|
||||||
// 是否为需映射至「中轻动力平台部」的部门(中轻 / 中重动力平台)
|
// 是否为需映射至「中轻动力平台部」的部门(中轻 / 中重动力平台 / 平台部)
|
||||||
isZQOrZZPowerPlatformDept(department) {
|
isZQOrZZPowerPlatformDept(department) {
|
||||||
if (!department) {
|
if (!department) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const normalized = String(department).replace(/·/g, '-')
|
const normalized = String(department).replace(/·/g, '-')
|
||||||
const displayName = this.formatDepartmentDisplay(normalized)
|
const displayName = this.formatDepartmentDisplay(normalized)
|
||||||
const aliasNames = ['中轻', '中重动力平台']
|
// 部门别名列表:这些部门都视为「中轻动力平台部」
|
||||||
|
const aliasNames = [
|
||||||
|
'中轻',
|
||||||
|
'中重动力平台',
|
||||||
|
'平台部',
|
||||||
|
'中轻动力平台部', // 完整名称
|
||||||
|
'中重动力平台部' // 完整名称
|
||||||
|
]
|
||||||
return aliasNames.some(
|
return aliasNames.some(
|
||||||
(alias) =>
|
(alias) =>
|
||||||
displayName === alias ||
|
displayName === alias ||
|
||||||
|
|||||||
@ -5,6 +5,36 @@
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
责任人管理
|
责任人管理
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search-section">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.department"
|
||||||
|
placeholder="搜索责任部门"
|
||||||
|
clearable
|
||||||
|
style="width: 180px; margin-right: 10px;"
|
||||||
|
@input="handleSearch"
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.subsystem"
|
||||||
|
placeholder="搜索子系统"
|
||||||
|
clearable
|
||||||
|
style="width: 180px; margin-right: 10px;"
|
||||||
|
@input="handleSearch"
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.username"
|
||||||
|
placeholder="搜索责任人"
|
||||||
|
clearable
|
||||||
|
style="width: 180px; margin-right: 10px;"
|
||||||
|
@input="handleSearch"
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.partsName"
|
||||||
|
placeholder="搜索状态代号"
|
||||||
|
clearable
|
||||||
|
style="width: 180px; margin-right: 10px;"
|
||||||
|
@input="handleSearch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-if="hasEditPermission()">
|
<div v-if="hasEditPermission()">
|
||||||
<el-button type="primary" @click="handleAdd">
|
<el-button type="primary" @click="handleAdd">
|
||||||
新增
|
新增
|
||||||
@ -36,8 +66,7 @@
|
|||||||
{{ formatDepartmentDisplay(scope.row.department) }}
|
{{ formatDepartmentDisplay(scope.row.department) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="subsystem" label="子系统" align="center" />
|
<el-table-column prop="partsName" label="项目编号" align="center" />
|
||||||
<el-table-column prop="partsName" label="状态代号" align="center" />
|
|
||||||
<el-table-column prop="username" label="责任人" width="250" align="center" />
|
<el-table-column prop="username" label="责任人" width="250" align="center" />
|
||||||
<el-table-column v-if="hasEditPermission()" label="操作" width="200" align="center">
|
<el-table-column v-if="hasEditPermission()" label="操作" width="200" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@ -308,7 +337,15 @@ export default {
|
|||||||
importFileList: [], // 导入文件列表
|
importFileList: [], // 导入文件列表
|
||||||
selectedImportFile: null, // 选中的导入文件
|
selectedImportFile: null, // 选中的导入文件
|
||||||
importing: false, // 导入中状态
|
importing: false, // 导入中状态
|
||||||
canViewData: false // 是否有查看数据的权限
|
canViewData: false, // 是否有查看数据的权限
|
||||||
|
// 搜索相关
|
||||||
|
searchForm: {
|
||||||
|
department: '',
|
||||||
|
subsystem: '',
|
||||||
|
username: '',
|
||||||
|
partsName: ''
|
||||||
|
},
|
||||||
|
allTableData: [] // 保存所有数据,用于前端搜索
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -521,8 +558,8 @@ export default {
|
|||||||
const request = {
|
const request = {
|
||||||
...api.GET_MANAGER_DATA,
|
...api.GET_MANAGER_DATA,
|
||||||
params: {
|
params: {
|
||||||
pageNumber: this.pagination.currentPage,
|
pageNumber: 1,
|
||||||
pageSize: this.pagination.pageSize
|
pageSize: 9999 // 加载所有数据用于前端搜索
|
||||||
},
|
},
|
||||||
disableSuccessMsg: true
|
disableSuccessMsg: true
|
||||||
}
|
}
|
||||||
@ -530,20 +567,72 @@ export default {
|
|||||||
.asyncThen((resp) => {
|
.asyncThen((resp) => {
|
||||||
// 处理返回数据,支持不同的数据结构
|
// 处理返回数据,支持不同的数据结构
|
||||||
if (resp && resp.data) {
|
if (resp && resp.data) {
|
||||||
this.tableData = resp.data.result
|
this.allTableData = resp.data.result || []
|
||||||
// 如果返回对象中有 total 字段
|
this.pagination.total = resp.data.count || this.allTableData.length
|
||||||
this.pagination.total = resp.data.count
|
// 应用搜索过滤
|
||||||
|
this.handleSearch()
|
||||||
} else {
|
} else {
|
||||||
|
this.allTableData = []
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
this.pagination.total = 0
|
this.pagination.total = 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.asyncErrorCatch((err) => {
|
.asyncErrorCatch((err) => {
|
||||||
console.error('加载管理数据失败:', err)
|
console.error('加载管理数据失败:', err)
|
||||||
|
this.allTableData = []
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
this.pagination.total = 0
|
this.pagination.total = 0
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 搜索过滤
|
||||||
|
handleSearch() {
|
||||||
|
let filteredData = [...this.allTableData]
|
||||||
|
|
||||||
|
// 按责任部门搜索
|
||||||
|
if (this.searchForm.department && this.searchForm.department.trim()) {
|
||||||
|
const deptKeyword = this.searchForm.department.trim().toLowerCase()
|
||||||
|
filteredData = filteredData.filter(item => {
|
||||||
|
const dept = this.formatDepartmentDisplay(item.department || '')
|
||||||
|
return dept.toLowerCase().includes(deptKeyword) ||
|
||||||
|
(item.department || '').toLowerCase().includes(deptKeyword)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按子系统搜索
|
||||||
|
if (this.searchForm.subsystem && this.searchForm.subsystem.trim()) {
|
||||||
|
const subsystemKeyword = this.searchForm.subsystem.trim().toLowerCase()
|
||||||
|
filteredData = filteredData.filter(item => {
|
||||||
|
const subsystem = item.subsystem || ''
|
||||||
|
return subsystem.toLowerCase().includes(subsystemKeyword)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按责任人搜索
|
||||||
|
if (this.searchForm.username && this.searchForm.username.trim()) {
|
||||||
|
const usernameKeyword = this.searchForm.username.trim().toLowerCase()
|
||||||
|
filteredData = filteredData.filter(item => {
|
||||||
|
const username = item.username || item.userName || ''
|
||||||
|
return username.toLowerCase().includes(usernameKeyword)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按状态代号搜索
|
||||||
|
if (this.searchForm.partsName && this.searchForm.partsName.trim()) {
|
||||||
|
const partsNameKeyword = this.searchForm.partsName.trim().toLowerCase()
|
||||||
|
filteredData = filteredData.filter(item => {
|
||||||
|
const partsName = item.partsName || ''
|
||||||
|
return partsName.toLowerCase().includes(partsNameKeyword)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新总数
|
||||||
|
this.pagination.total = filteredData.length
|
||||||
|
|
||||||
|
// 分页处理
|
||||||
|
const startIndex = (this.pagination.currentPage - 1) * this.pagination.pageSize
|
||||||
|
const endIndex = startIndex + this.pagination.pageSize
|
||||||
|
this.tableData = filteredData.slice(startIndex, endIndex)
|
||||||
|
},
|
||||||
loadDepartmentList() {
|
loadDepartmentList() {
|
||||||
const request = {
|
const request = {
|
||||||
...api.GET_DEPT_OF_USER,
|
...api.GET_DEPT_OF_USER,
|
||||||
@ -983,12 +1072,12 @@ export default {
|
|||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.pagination.pageSize = val
|
this.pagination.pageSize = val
|
||||||
this.pagination.currentPage = 1 // 重置到第一页
|
this.pagination.currentPage = 1 // 重置到第一页
|
||||||
this.loadManagerData()
|
this.handleSearch() // 重新应用搜索和分页
|
||||||
},
|
},
|
||||||
// 处理当前页变化
|
// 处理当前页变化
|
||||||
handleCurrentChange(val) {
|
handleCurrentChange(val) {
|
||||||
this.pagination.currentPage = val
|
this.pagination.currentPage = val
|
||||||
this.loadManagerData()
|
this.handleSearch() // 重新应用搜索和分页
|
||||||
},
|
},
|
||||||
// 处理刷新
|
// 处理刷新
|
||||||
handleRefresh() {
|
handleRefresh() {
|
||||||
@ -1335,6 +1424,7 @@ export default {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.comment-text {
|
.comment-text {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
@ -1344,11 +1434,15 @@ export default {
|
|||||||
color: #303133;
|
color: #303133;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
-webkit-box-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
.search-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-section {
|
.table-section {
|
||||||
|
|||||||
@ -104,6 +104,9 @@
|
|||||||
<th class="param-column">
|
<th class="param-column">
|
||||||
参数名称
|
参数名称
|
||||||
</th>
|
</th>
|
||||||
|
<th class="unit-column">
|
||||||
|
单位
|
||||||
|
</th>
|
||||||
<th v-for="(model, index) in comparisonModels" :key="index" class="model-column">
|
<th v-for="(model, index) in comparisonModels" :key="index" class="model-column">
|
||||||
<div class="model-header">
|
<div class="model-header">
|
||||||
<div v-if="model.name" class="model-name"
|
<div v-if="model.name" class="model-name"
|
||||||
@ -145,6 +148,9 @@
|
|||||||
@click.stop="handleHideParam(param)"
|
@click.stop="handleHideParam(param)"
|
||||||
></i>
|
></i>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="unit-column">
|
||||||
|
{{ param.unit || '-' }}
|
||||||
|
</td>
|
||||||
<td
|
<td
|
||||||
v-for="(model, modelIndex) in comparisonModels"
|
v-for="(model, modelIndex) in comparisonModels"
|
||||||
:key="modelIndex"
|
:key="modelIndex"
|
||||||
@ -490,7 +496,8 @@ export default {
|
|||||||
subsystemName: subsystemName,
|
subsystemName: subsystemName,
|
||||||
parameterId: parameterId,
|
parameterId: parameterId,
|
||||||
partsName: partsName, // 保存原始的 partsName
|
partsName: partsName, // 保存原始的 partsName
|
||||||
displayPartsName: displayPartsName // 保存用于显示的零部件名称
|
displayPartsName: displayPartsName, // 保存用于显示的零部件名称
|
||||||
|
unit: item.unit || '' // 保存单位
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2481,7 +2488,8 @@ export default {
|
|||||||
parameterId: param.parameterId || '',
|
parameterId: param.parameterId || '',
|
||||||
parameterName: param.parameterName || '',
|
parameterName: param.parameterName || '',
|
||||||
partsName: param.partsName || '',
|
partsName: param.partsName || '',
|
||||||
subsystem: item.subsystem // 保存子系统名称
|
subsystem: item.subsystem, // 保存子系统名称
|
||||||
|
unit: param.unit || '' // 保存单位
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -2858,6 +2866,13 @@ export default {
|
|||||||
z-index: 15;
|
z-index: 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.unit-column {
|
||||||
|
width: 80px;
|
||||||
|
min-width: 80px;
|
||||||
|
left: 460px;
|
||||||
|
z-index: 15;
|
||||||
|
}
|
||||||
|
|
||||||
&.model-column {
|
&.model-column {
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -2957,7 +2972,8 @@ export default {
|
|||||||
td {
|
td {
|
||||||
&.subsystem-column,
|
&.subsystem-column,
|
||||||
&.parts-column,
|
&.parts-column,
|
||||||
&.param-column {
|
&.param-column,
|
||||||
|
&.unit-column {
|
||||||
background: #f5f7fa;
|
background: #f5f7fa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3007,6 +3023,14 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.unit-column {
|
||||||
|
position: sticky;
|
||||||
|
left: 460px;
|
||||||
|
background: white;
|
||||||
|
z-index: 5;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&.model-column {
|
&.model-column {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,9 @@
|
|||||||
<el-button v-if="hasTemplateManagementEditPermission()" class="import-btn" @click="handleImportTemplate()">
|
<el-button v-if="hasTemplateManagementEditPermission()" class="import-btn" @click="handleImportTemplate()">
|
||||||
导入参数模板
|
导入参数模板
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button v-if="hasTemplateManagementEditPermission()" type="primary" @click="handleShowOrderDialog">
|
||||||
|
调整排序
|
||||||
|
</el-button>
|
||||||
<!-- <el-button v-if="hasTemplateManagementEditPermission()" type="primary" @click="handleAddTemplate()">
|
<!-- <el-button v-if="hasTemplateManagementEditPermission()" type="primary" @click="handleAddTemplate()">
|
||||||
添加参数模板
|
添加参数模板
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
@ -232,6 +235,37 @@
|
|||||||
>
|
>
|
||||||
<div class="error-list"> {{ errorList }} </div>
|
<div class="error-list"> {{ errorList }} </div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
title="调整排序"
|
||||||
|
:visible.sync="orderDialogVisible"
|
||||||
|
width="600px"
|
||||||
|
append-to-body
|
||||||
|
@close="handleOrderDialogClose"
|
||||||
|
>
|
||||||
|
<div class="order-dialog-content">
|
||||||
|
<div class="order-tip" style="margin-bottom: 10px; color: #909399; font-size: 12px">
|
||||||
|
提示:拖动行可调整排序,拖动后排序号会自动更新
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="orderList"
|
||||||
|
row-key="id"
|
||||||
|
class="order-table"
|
||||||
|
max-height="600"
|
||||||
|
>
|
||||||
|
<el-table-column label="排序号" width="80" align="center">
|
||||||
|
<template slot-scope="{ $index }">
|
||||||
|
{{ $index + 1 }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="模板名称" prop="templateName" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleOrderDialogClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="updatingOrder" @click="handleUpdateOrder">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -280,7 +314,11 @@ export default {
|
|||||||
userId: getUserId(),
|
userId: getUserId(),
|
||||||
errorDialogVisible: false,
|
errorDialogVisible: false,
|
||||||
templateManagementPermissions: [], // 暂存 menuPath 为 "数据录入/模板管理" 的权限数组
|
templateManagementPermissions: [], // 暂存 menuPath 为 "数据录入/模板管理" 的权限数组
|
||||||
fromTodo: false // 是否从待办页面进入
|
fromTodo: false, // 是否从待办页面进入
|
||||||
|
orderDialogVisible: false,
|
||||||
|
orderList: [],
|
||||||
|
updatingOrder: false,
|
||||||
|
dragSortHandler: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -1090,13 +1128,130 @@ export default {
|
|||||||
this.templateSelectLoading = false
|
this.templateSelectLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 生成UUID
|
|
||||||
generateUUID() {
|
generateUUID() {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
const r = (Math.random() * 16) | 0
|
const r = (Math.random() * 16) | 0
|
||||||
const v = c === 'x' ? r : (r & 0x3) | 0x8
|
const v = c === 'x' ? r : (r & 0x3) | 0x8
|
||||||
return v.toString(16)
|
return v.toString(16)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
handleShowOrderDialog() {
|
||||||
|
const request = {
|
||||||
|
...api.GET_MODEL_LIST,
|
||||||
|
params: {
|
||||||
|
pageNumber: 1,
|
||||||
|
pageSize: 999
|
||||||
|
},
|
||||||
|
disableSuccessMsg: true
|
||||||
|
}
|
||||||
|
this.$request(request, false)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
const list = resp.data.result || []
|
||||||
|
this.orderList = list.map((item, index) => ({
|
||||||
|
id: item.id || item.row_id || `temp_${index}_${Date.now()}`,
|
||||||
|
templateName: item.templateName || item.po_name,
|
||||||
|
orderNum: item.orderNum || item.order_num || (index + 1)
|
||||||
|
}))
|
||||||
|
this.orderDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initDragSort()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('加载模板列表失败:', err)
|
||||||
|
this.$message.error('加载模板列表失败')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleOrderDialogClose() {
|
||||||
|
this.orderDialogVisible = false
|
||||||
|
this.orderList = []
|
||||||
|
},
|
||||||
|
initDragSort() {
|
||||||
|
const table = document.querySelector('.order-table .el-table__body-wrapper tbody')
|
||||||
|
if (!table) return
|
||||||
|
const rows = table.querySelectorAll('tr')
|
||||||
|
rows.forEach((row) => {
|
||||||
|
row.draggable = true
|
||||||
|
row.style.cursor = 'move'
|
||||||
|
})
|
||||||
|
if (this.dragSortHandler) {
|
||||||
|
table.removeEventListener('dragstart', this.dragSortHandler.dragstart)
|
||||||
|
table.removeEventListener('dragend', this.dragSortHandler.dragend)
|
||||||
|
table.removeEventListener('dragover', this.dragSortHandler.dragover)
|
||||||
|
table.removeEventListener('drop', this.dragSortHandler.drop)
|
||||||
|
}
|
||||||
|
let draggedIndex = null
|
||||||
|
const dragstartHandler = (e) => {
|
||||||
|
const row = e.target.closest('tr')
|
||||||
|
if (!row) return
|
||||||
|
const rows = Array.from(table.querySelectorAll('tr'))
|
||||||
|
draggedIndex = rows.indexOf(row)
|
||||||
|
row.style.opacity = '0.5'
|
||||||
|
e.dataTransfer.effectAllowed = 'move'
|
||||||
|
}
|
||||||
|
const dragendHandler = (e) => {
|
||||||
|
const row = e.target.closest('tr')
|
||||||
|
if (row) row.style.opacity = '1'
|
||||||
|
draggedIndex = null
|
||||||
|
}
|
||||||
|
const dragoverHandler = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.dataTransfer.dropEffect = 'move'
|
||||||
|
}
|
||||||
|
const dropHandler = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const targetRow = e.target.closest('tr')
|
||||||
|
if (!targetRow || draggedIndex === null) return
|
||||||
|
const rows = Array.from(table.querySelectorAll('tr'))
|
||||||
|
const targetIndex = rows.indexOf(targetRow)
|
||||||
|
if (draggedIndex !== targetIndex) {
|
||||||
|
const newOrderList = [...this.orderList]
|
||||||
|
const draggedItem = newOrderList[draggedIndex]
|
||||||
|
newOrderList.splice(draggedIndex, 1)
|
||||||
|
newOrderList.splice(targetIndex, 0, draggedItem)
|
||||||
|
this.orderList = newOrderList
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initDragSort()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.addEventListener('dragstart', dragstartHandler)
|
||||||
|
table.addEventListener('dragend', dragendHandler)
|
||||||
|
table.addEventListener('dragover', dragoverHandler)
|
||||||
|
table.addEventListener('drop', dropHandler)
|
||||||
|
this.dragSortHandler = {
|
||||||
|
dragstart: dragstartHandler,
|
||||||
|
dragend: dragendHandler,
|
||||||
|
dragover: dragoverHandler,
|
||||||
|
drop: dropHandler
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleUpdateOrder() {
|
||||||
|
this.updatingOrder = true
|
||||||
|
const updateList = this.orderList.map((item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
orderNum: index + 1
|
||||||
|
}))
|
||||||
|
const request = {
|
||||||
|
...api.UPDATE_TEMPLATE_ORDER,
|
||||||
|
params: {
|
||||||
|
items: updateList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
this.$message.success('排序更新成功')
|
||||||
|
this.handleOrderDialogClose()
|
||||||
|
this.loadData()
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('更新排序失败:', err)
|
||||||
|
this.$message.error('更新排序失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.updatingOrder = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1299,4 +1454,24 @@ export default {
|
|||||||
::v-deep .el-button {
|
::v-deep .el-button {
|
||||||
line-height: 0.85 !important;
|
line-height: 0.85 !important;
|
||||||
}
|
}
|
||||||
|
.order-dialog-content {
|
||||||
|
.order-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.order-tip {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #f4f4f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
::v-deep .el-table__body tr {
|
||||||
|
cursor: move;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
::v-deep .el-table__body tr:hover {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
::v-deep .el-table__body tr[draggable="true"] {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -944,6 +944,13 @@ export default {
|
|||||||
width: '100',
|
width: '100',
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'parameterValue',
|
||||||
|
label: '参数值',
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
minWidth: '120',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'isNumber',
|
prop: 'isNumber',
|
||||||
label: '数值类型',
|
label: '数值类型',
|
||||||
@ -1049,6 +1056,13 @@ export default {
|
|||||||
width: '100',
|
width: '100',
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'parameterValue',
|
||||||
|
label: '参数值',
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
minWidth: '120',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'isNumber',
|
prop: 'isNumber',
|
||||||
label: '数值类型',
|
label: '数值类型',
|
||||||
@ -1391,6 +1405,12 @@ export default {
|
|||||||
if (this.detail && this.detail.flowId) {
|
if (this.detail && this.detail.flowId) {
|
||||||
this.getApprovalSpet()
|
this.getApprovalSpet()
|
||||||
}
|
}
|
||||||
|
// 如果是从待办进入,自动加载数据并显示
|
||||||
|
if (this.fromTodo && this.flowId) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.loadData()
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 加载用户自身角色权限
|
// 加载用户自身角色权限
|
||||||
|
|||||||
@ -1,11 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="permission-management-page custom-page">
|
<div class="permission-management-page custom-page">
|
||||||
<div class="page-header">
|
<!-- 人员管理组件 -->
|
||||||
<div class="title">
|
<apaas-custom-roleMemberManagement
|
||||||
权限管理
|
v-if="showRoleMemberManagement"
|
||||||
|
:role-id="currentRoleId"
|
||||||
|
:role-name="currentRoleName"
|
||||||
|
@back="handleBackFromRoleMember"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 权限管理主页面 -->
|
||||||
|
<div v-if="!showRoleMemberManagement">
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="title">
|
||||||
|
权限管理
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="page-content">
|
||||||
<div class="page-content">
|
|
||||||
<div class="header-section">
|
<div class="header-section">
|
||||||
<el-button type="primary" @click="handleAddRole">
|
<el-button type="primary" @click="handleAddRole">
|
||||||
新增角色
|
新增角色
|
||||||
@ -78,6 +88,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 新增/编辑对话框 -->
|
<!-- 新增/编辑对话框 -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@ -146,7 +157,7 @@
|
|||||||
<el-dialog
|
<el-dialog
|
||||||
title="人员配置"
|
title="人员配置"
|
||||||
:visible.sync="personConfigDialogVisible"
|
:visible.sync="personConfigDialogVisible"
|
||||||
width="500px"
|
width="800px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:modal="false"
|
:modal="false"
|
||||||
class="person-config-dialog"
|
class="person-config-dialog"
|
||||||
@ -194,34 +205,28 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 配置人员模式 -->
|
<!-- 配置人员模式 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- <el-form-item label="责任部门:" prop="department">
|
<el-form-item label="搜索人员:">
|
||||||
<el-cascader
|
<el-input
|
||||||
ref="departmentCascader"
|
v-model="personSearchKeyword"
|
||||||
v-model="personConfigFormData.department"
|
placeholder="在已选人员中搜索人名"
|
||||||
:options="departmentList"
|
|
||||||
:props="departmentCascaderProps"
|
|
||||||
filterable
|
|
||||||
placeholder="请选择责任部门"
|
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="handlePersonDepartmentChange"
|
@input="handlePersonSearchInList"
|
||||||
/>
|
/>
|
||||||
</el-form-item> -->
|
</el-form-item>
|
||||||
<el-form-item label="人员:" prop="person">
|
<el-form-item label="添加人员:">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="personConfigFormData.person"
|
v-model="personToAdd"
|
||||||
multiple
|
|
||||||
filterable
|
filterable
|
||||||
remote
|
remote
|
||||||
reserve-keyword
|
reserve-keyword
|
||||||
collapse-tags
|
placeholder="请输入人员姓名进行搜索并添加"
|
||||||
:max-collapse-tags="3"
|
|
||||||
placeholder="请输入人员姓名进行搜索"
|
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
clearable
|
clearable
|
||||||
:remote-method="queryPersonByDepartment"
|
:remote-method="queryPersonByDepartment"
|
||||||
:loading="personSearchLoading"
|
:loading="personSearchLoading"
|
||||||
class="person-select"
|
class="person-select"
|
||||||
|
@change="handleAddPersonToList"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="person in personOptions"
|
v-for="person in personOptions"
|
||||||
@ -234,6 +239,32 @@
|
|||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="已选人员:">
|
||||||
|
<el-table
|
||||||
|
:data="filteredPersonList"
|
||||||
|
border
|
||||||
|
max-height="300"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="username" label="姓名" align="center" />
|
||||||
|
<el-table-column prop="userNumber" label="ID" align="center" />
|
||||||
|
<el-table-column label="操作" width="80" align="center">
|
||||||
|
<template slot-scope="{ row }">
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
style="color: #f56c6c"
|
||||||
|
@click="handleRemovePersonFromList(row)"
|
||||||
|
>
|
||||||
|
移除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div style="margin-top: 8px; color: #909399; font-size: 12px">
|
||||||
|
共 {{ personConfigFormData.person.length }} 人
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
@ -348,7 +379,11 @@ export default {
|
|||||||
roleDescription: '',
|
roleDescription: '',
|
||||||
roleId: '' // 编辑时使用
|
roleId: '' // 编辑时使用
|
||||||
},
|
},
|
||||||
addRoleFormRules: {
|
// 人员管理页面相关
|
||||||
|
showRoleMemberManagement: false,
|
||||||
|
currentRoleId: '',
|
||||||
|
currentRoleName: '',
|
||||||
|
addRoleFormRules: {
|
||||||
roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
|
roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
|
||||||
roleCode: [{ required: true, message: '请输入角色代码', trigger: 'blur' }],
|
roleCode: [{ required: true, message: '请输入角色代码', trigger: 'blur' }],
|
||||||
roleDescription: [{ required: true, message: '请输入角色描述', trigger: 'blur' }]
|
roleDescription: [{ required: true, message: '请输入角色描述', trigger: 'blur' }]
|
||||||
@ -383,6 +418,9 @@ export default {
|
|||||||
},
|
},
|
||||||
personOptions: [], // 人员选项列表
|
personOptions: [], // 人员选项列表
|
||||||
personSearchLoading: false, // 人员搜索loading状态
|
personSearchLoading: false, // 人员搜索loading状态
|
||||||
|
personSearchKeyword: '', // 已选人员搜索关键字
|
||||||
|
personToAdd: '', // 待添加的人员ID
|
||||||
|
selectedPersonList: [], // 已选人员完整信息列表 [{ userId, username, userNumber }]
|
||||||
selectedDepartmentOptions: [], // 从接口解析的已选部门选项 { value, label },用于反显时显示部门名称
|
selectedDepartmentOptions: [], // 从接口解析的已选部门选项 { value, label },用于反显时显示部门名称
|
||||||
personConfigFormRules: {
|
personConfigFormRules: {
|
||||||
department: [
|
department: [
|
||||||
@ -433,6 +471,21 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
filteredPersonList() {
|
||||||
|
let list = []
|
||||||
|
if (!this.personSearchKeyword || this.personSearchKeyword.trim() === '') {
|
||||||
|
list = this.selectedPersonList
|
||||||
|
} else {
|
||||||
|
//列表展示人员倒序排序
|
||||||
|
const keyword = this.personSearchKeyword.trim().toLowerCase()
|
||||||
|
list = this.selectedPersonList.filter((person) => {
|
||||||
|
const name = (person.username || '').toLowerCase()
|
||||||
|
const number = (person.userNumber || '').toLowerCase()
|
||||||
|
return name.includes(keyword) || number.includes(keyword)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return list.slice().reverse()
|
||||||
|
},
|
||||||
dialogTitle() {
|
dialogTitle() {
|
||||||
return this.dialogMode === 'add' ? '新增' : '修改'
|
return this.dialogMode === 'add' ? '新增' : '修改'
|
||||||
},
|
},
|
||||||
@ -1507,96 +1560,21 @@ export default {
|
|||||||
// 不显示错误提示,因为可能是新角色没有权限数据
|
// 不显示错误提示,因为可能是新角色没有权限数据
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 人员配置
|
// 人员配置 - 显示人员管理页面
|
||||||
handlePersonConfig(row) {
|
handlePersonConfig(row) {
|
||||||
this.personConfigFormData = {
|
console.log('打开人员管理页面:', row)
|
||||||
configType: 'person',
|
this.currentRoleId = row.rowId || row.id || ''
|
||||||
department: '',
|
this.currentRoleName = row.roleName || ''
|
||||||
person: [], // userId 数组
|
this.showRoleMemberManagement = true
|
||||||
selectDeptId: '',
|
|
||||||
selectDeptName: '',
|
|
||||||
selectDeptIds: [],
|
|
||||||
roleId: row.rowId || row.id || '',
|
|
||||||
roleName: row.roleName || ''
|
|
||||||
}
|
|
||||||
this.selectedDepartmentOptions = []
|
|
||||||
const request = {
|
|
||||||
...api.CHECK_ROLE_USER_DEPT,
|
|
||||||
params: {
|
|
||||||
roleId: row.rowId || row.id || ''
|
|
||||||
},
|
|
||||||
disableSuccessMsg: true
|
|
||||||
}
|
|
||||||
this.$request(request)
|
|
||||||
.asyncThen((resp) => {
|
|
||||||
if (resp && resp.data) {
|
|
||||||
// 解析返回数据,格式:{ "部门": ["部门名-部门ID"], "人员": ["李亚松-yc90117847"] }
|
|
||||||
const respData = resp.data
|
|
||||||
const personArray = respData['人员'] || respData.person || []
|
|
||||||
const departmentArray = respData['部门'] || respData.department || []
|
|
||||||
|
|
||||||
// 解析部门数组,格式:["部门名-部门ID"] 或 [{ deptId, deptName }],提取部门ID(统一字符串)并保存部门名称用于反显
|
|
||||||
if (departmentArray.length > 0) {
|
|
||||||
const deptIds = []
|
|
||||||
const optionsFromApi = []
|
|
||||||
departmentArray.forEach((item) => {
|
|
||||||
if (typeof item === 'string' && item.includes('-')) {
|
|
||||||
const parts = item.split('-')
|
|
||||||
if (parts.length >= 2) {
|
|
||||||
const deptName = parts[0]
|
|
||||||
const deptId = parts.slice(1).join('-')
|
|
||||||
const idStr = deptId == null ? '' : String(deptId)
|
|
||||||
deptIds.push(idStr)
|
|
||||||
optionsFromApi.push({ value: idStr, label: deptName || idStr })
|
|
||||||
}
|
|
||||||
} else if (item && typeof item === 'object' && (item.deptId != null || item.id != null)) {
|
|
||||||
const id = item.deptId != null ? item.deptId : item.id
|
|
||||||
const name = item.deptName || item.name || item.label || ''
|
|
||||||
const idStr = id == null ? '' : String(id)
|
|
||||||
deptIds.push(idStr)
|
|
||||||
optionsFromApi.push({ value: idStr, label: name || idStr })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.personConfigFormData.selectDeptIds = deptIds
|
|
||||||
this.personConfigFormData.department = deptIds
|
|
||||||
this.selectedDepartmentOptions = optionsFromApi
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析人员数组,格式:["userName-userId"]
|
|
||||||
const userIds = []
|
|
||||||
const personOptionsMap = new Map()
|
|
||||||
personArray.forEach((personStr) => {
|
|
||||||
if (typeof personStr === 'string' && personStr.includes('-')) {
|
|
||||||
const parts = personStr.split('-')
|
|
||||||
if (parts.length >= 2) {
|
|
||||||
const userName = parts[0]
|
|
||||||
const userId = parts.slice(1).join('-') // 处理 userId 中可能包含 - 的情况
|
|
||||||
userIds.push(userId)
|
|
||||||
// 构建选项对象
|
|
||||||
personOptionsMap.set(userId, {
|
|
||||||
userId: userId,
|
|
||||||
username: userName,
|
|
||||||
userNumber: userId // userNumber 使用 userId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// 设置已选择的人员ID数组
|
|
||||||
this.personConfigFormData.person = userIds
|
|
||||||
// 设置选项(用于显示已选择的人员)
|
|
||||||
this.personOptions = Array.from(personOptionsMap.values())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.asyncErrorCatch((err) => {
|
|
||||||
console.error('加载人员列表失败:', err)
|
|
||||||
})
|
|
||||||
this.personConfigDialogVisible = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.personConfigForm) {
|
|
||||||
this.$refs.personConfigForm.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
// 从人员管理页面返回
|
||||||
|
handleBackFromRoleMember() {
|
||||||
|
console.log('从人员管理页面返回')
|
||||||
|
this.showRoleMemberManagement = false
|
||||||
|
this.currentRoleId = ''
|
||||||
|
this.currentRoleName = ''
|
||||||
|
},
|
||||||
|
|
||||||
// 配置类型切换
|
// 配置类型切换
|
||||||
handleConfigTypeChange(value) {
|
handleConfigTypeChange(value) {
|
||||||
// 切换到配置部门时:将 department 中的部门 id 数组同步到 selectDeptIds,保证 el-select 能反显(并统一为字符串以匹配选项)
|
// 切换到配置部门时:将 department 中的部门 id 数组同步到 selectDeptIds,保证 el-select 能反显(并统一为字符串以匹配选项)
|
||||||
@ -1960,6 +1938,9 @@ export default {
|
|||||||
roleName: ''
|
roleName: ''
|
||||||
}
|
}
|
||||||
this.personOptions = []
|
this.personOptions = []
|
||||||
|
this.personSearchKeyword = ''
|
||||||
|
this.personToAdd = ''
|
||||||
|
this.selectedPersonList = []
|
||||||
// 清除定时器和请求
|
// 清除定时器和请求
|
||||||
if (this.personSearchTimer) {
|
if (this.personSearchTimer) {
|
||||||
clearTimeout(this.personSearchTimer)
|
clearTimeout(this.personSearchTimer)
|
||||||
@ -1970,6 +1951,40 @@ export default {
|
|||||||
this.$refs.personConfigForm.clearValidate()
|
this.$refs.personConfigForm.clearValidate()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handlePersonSearchInList() {
|
||||||
|
},
|
||||||
|
handleAddPersonToList(userId) {
|
||||||
|
if (!userId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const person = this.personOptions.find((p) => p.userId === userId)
|
||||||
|
if (!person) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const exists = this.selectedPersonList.some((p) => p.userId === userId)
|
||||||
|
if (exists) {
|
||||||
|
this.$message.warning('该人员已在列表中')
|
||||||
|
this.personToAdd = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.selectedPersonList.push({
|
||||||
|
userId: person.userId,
|
||||||
|
username: person.username,
|
||||||
|
userNumber: person.userNumber
|
||||||
|
})
|
||||||
|
this.personConfigFormData.person.push(userId)
|
||||||
|
this.personToAdd = ''
|
||||||
|
},
|
||||||
|
handleRemovePersonFromList(row) {
|
||||||
|
const index = this.selectedPersonList.findIndex((p) => p.userId === row.userId)
|
||||||
|
if (index > -1) {
|
||||||
|
this.selectedPersonList.splice(index, 1)
|
||||||
|
const idIndex = this.personConfigFormData.person.indexOf(row.userId)
|
||||||
|
if (idIndex > -1) {
|
||||||
|
this.personConfigFormData.person.splice(idIndex, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
// 编辑角色(编辑角色名称和描述)
|
// 编辑角色(编辑角色名称和描述)
|
||||||
handleEdit(row) {
|
handleEdit(row) {
|
||||||
this.addRoleMode = 'edit'
|
this.addRoleMode = 'edit'
|
||||||
|
|||||||
@ -0,0 +1,520 @@
|
|||||||
|
<template>
|
||||||
|
<div class="role-member-management-page custom-page">
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-arrow-left"
|
||||||
|
class="back-button"
|
||||||
|
@click="handleBack"
|
||||||
|
>
|
||||||
|
返回
|
||||||
|
</el-button>
|
||||||
|
<div class="title-info">
|
||||||
|
<span class="title">人员管理</span>
|
||||||
|
<span class="role-tip">当前选择角色:<span class="role-name">{{ roleName }}</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page-content">
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-section">
|
||||||
|
<div class="search-form">
|
||||||
|
<div class="search-item">
|
||||||
|
<span class="label">成员名称</span>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.memberName"
|
||||||
|
placeholder="请输入成员名称"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item">
|
||||||
|
<span class="label">成员编码</span>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.memberCode"
|
||||||
|
placeholder="请输入成员编码"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item">
|
||||||
|
<span class="label">部门</span>
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.department"
|
||||||
|
placeholder="请输入部门"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-actions">
|
||||||
|
<el-button type="primary" @click="handleSearch">
|
||||||
|
查询
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleReset">
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作区域 -->
|
||||||
|
<div class="action-section">
|
||||||
|
<el-button type="primary" @click="handleAddMember">
|
||||||
|
添加成员
|
||||||
|
</el-button>
|
||||||
|
<el-button :disabled="selectedMembers.length === 0" @click="handleDeleteMember">
|
||||||
|
删除成员
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<div class="table-section">
|
||||||
|
<el-table
|
||||||
|
ref="memberTable"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="username" label="成员名称" min-width="120" align="center" />
|
||||||
|
<el-table-column prop="userNumber" label="成员编码" min-width="120" align="center" />
|
||||||
|
<el-table-column label="部门" min-width="200" align="center" show-overflow-tooltip>
|
||||||
|
<template slot-scope="{ row }">
|
||||||
|
{{ formatDepartment(row) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="pagination-section">
|
||||||
|
<el-pagination
|
||||||
|
:current-page="pagination.currentPage"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
:page-size="pagination.pageSize"
|
||||||
|
:total="pagination.total"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 添加成员弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="添加成员"
|
||||||
|
:visible.sync="addMemberDialogVisible"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
@close="handleAddMemberDialogClose"
|
||||||
|
>
|
||||||
|
<el-form ref="addMemberForm" :model="addMemberFormData" label-width="100px">
|
||||||
|
<el-form-item label="搜索人员:">
|
||||||
|
<el-select
|
||||||
|
v-model="addMemberFormData.selectedUsers"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
multiple
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="请输入人员姓名进行搜索"
|
||||||
|
style="width: 100%"
|
||||||
|
:remote-method="queryPerson"
|
||||||
|
:loading="personSearchLoading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="person in personOptions"
|
||||||
|
:key="person.userNumber"
|
||||||
|
:value="person.userId"
|
||||||
|
:label="person.username"
|
||||||
|
>
|
||||||
|
<span>{{ person.username }}</span>
|
||||||
|
<span style="float: right; color: #8492a6; font-size: 12px">{{ person.userNumber }}</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleAddMemberDialogClose">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" :loading="addMemberSubmitting" @click="handleAddMemberSubmit">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import api from '@/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'RoleMemberManagement',
|
||||||
|
props: {
|
||||||
|
roleId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
roleName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchForm: {
|
||||||
|
memberName: '',
|
||||||
|
memberCode: '',
|
||||||
|
department: ''
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
selectedMembers: [],
|
||||||
|
pagination: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
addMemberDialogVisible: false,
|
||||||
|
addMemberFormData: {
|
||||||
|
selectedUsers: []
|
||||||
|
},
|
||||||
|
personOptions: [],
|
||||||
|
personSearchLoading: false,
|
||||||
|
addMemberSubmitting: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
console.log('人员管理组件 mounted, roleId:', this.roleId, 'roleName:', this.roleName)
|
||||||
|
this.loadMemberList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 格式化部门显示:姓名/工号/部门
|
||||||
|
formatDepartment(row) {
|
||||||
|
const parts = []
|
||||||
|
if (row.username) parts.push(row.username)
|
||||||
|
if (row.userNumber) parts.push(row.userNumber)
|
||||||
|
if (row.department) parts.push(row.department)
|
||||||
|
return parts.join('/')
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
this.$emit('back')
|
||||||
|
},
|
||||||
|
handleSearch() {
|
||||||
|
this.pagination.currentPage = 1
|
||||||
|
this.loadMemberList()
|
||||||
|
},
|
||||||
|
handleReset() {
|
||||||
|
this.searchForm = {
|
||||||
|
memberName: '',
|
||||||
|
memberCode: '',
|
||||||
|
department: ''
|
||||||
|
}
|
||||||
|
this.pagination.currentPage = 1
|
||||||
|
this.loadMemberList()
|
||||||
|
},
|
||||||
|
handleAddMember() {
|
||||||
|
this.addMemberDialogVisible = true
|
||||||
|
this.addMemberFormData.selectedUsers = []
|
||||||
|
this.personOptions = []
|
||||||
|
},
|
||||||
|
handleDeleteMember() {
|
||||||
|
if (this.selectedMembers.length === 0) {
|
||||||
|
this.$message.warning('请先选择要删除的成员')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm(`确定要删除选中的 ${this.selectedMembers.length} 个成员吗?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.deleteMembers()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.selectedMembers = selection
|
||||||
|
},
|
||||||
|
handleSizeChange(size) {
|
||||||
|
this.pagination.pageSize = size
|
||||||
|
this.pagination.currentPage = 1
|
||||||
|
this.loadMemberList()
|
||||||
|
},
|
||||||
|
handleCurrentChange(page) {
|
||||||
|
this.pagination.currentPage = page
|
||||||
|
this.loadMemberList()
|
||||||
|
},
|
||||||
|
loadMemberList() {
|
||||||
|
const request = {
|
||||||
|
...api.CHECK_ROLE_USER_DEPT,
|
||||||
|
params: {
|
||||||
|
roleId: this.roleId
|
||||||
|
},
|
||||||
|
disableSuccessMsg: true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
if (resp && resp.data) {
|
||||||
|
const respData = resp.data
|
||||||
|
const personArray = respData['人员'] || respData.person || []
|
||||||
|
|
||||||
|
// 解析人员数组
|
||||||
|
// 格式:["周杰-ID:100771324098969075712-userNumber:yc90117846-department:"]
|
||||||
|
const members = []
|
||||||
|
personArray.forEach((personStr) => {
|
||||||
|
if (typeof personStr === 'string') {
|
||||||
|
// 提取用户名(第一个 - 之前)
|
||||||
|
const nameMatch = personStr.match(/^([^-]+)/)
|
||||||
|
const username = nameMatch ? nameMatch[1] : ''
|
||||||
|
|
||||||
|
// 提取ID
|
||||||
|
const idMatch = personStr.match(/ID:([^-]+)/)
|
||||||
|
const userId = idMatch ? idMatch[1] : ''
|
||||||
|
|
||||||
|
// 提取userNumber(成员编码)
|
||||||
|
const userNumberMatch = personStr.match(/userNumber:([^-]+)/)
|
||||||
|
const userNumber = userNumberMatch ? userNumberMatch[1] : ''
|
||||||
|
|
||||||
|
// 提取department(部门)
|
||||||
|
const deptMatch = personStr.match(/department:(.+)$/)
|
||||||
|
const department = deptMatch ? deptMatch[1] : ''
|
||||||
|
|
||||||
|
if (username && userId) {
|
||||||
|
members.push({
|
||||||
|
userId: userId,
|
||||||
|
username: username,
|
||||||
|
userNumber: userNumber, // 成员编码(用户工号)
|
||||||
|
department: department // 部门
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 应用搜索过滤
|
||||||
|
let filteredMembers = members
|
||||||
|
if (this.searchForm.memberName) {
|
||||||
|
filteredMembers = filteredMembers.filter(m =>
|
||||||
|
m.username && m.username.includes(this.searchForm.memberName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (this.searchForm.memberCode) {
|
||||||
|
filteredMembers = filteredMembers.filter(m =>
|
||||||
|
m.userNumber && m.userNumber.includes(this.searchForm.memberCode)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (this.searchForm.department) {
|
||||||
|
filteredMembers = filteredMembers.filter(m =>
|
||||||
|
m.department && m.department.includes(this.searchForm.department)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页处理
|
||||||
|
this.pagination.total = filteredMembers.length
|
||||||
|
const startIndex = (this.pagination.currentPage - 1) * this.pagination.pageSize
|
||||||
|
const endIndex = startIndex + this.pagination.pageSize
|
||||||
|
this.tableData = filteredMembers.slice(startIndex, endIndex)
|
||||||
|
} else {
|
||||||
|
this.tableData = []
|
||||||
|
this.pagination.total = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('加载成员列表失败:', err)
|
||||||
|
this.$message.error('加载成员列表失败,请稍后重试')
|
||||||
|
this.tableData = []
|
||||||
|
this.pagination.total = 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
queryPerson(query) {
|
||||||
|
if (!query || query.trim() === '') {
|
||||||
|
this.personOptions = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.personSearchLoading = true
|
||||||
|
const request = {
|
||||||
|
...api.GET_ALLUSERS,
|
||||||
|
params: {
|
||||||
|
name: query.trim()
|
||||||
|
},
|
||||||
|
disableSuccessMsg: true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
const respData = resp && resp.data
|
||||||
|
let result = []
|
||||||
|
if (Array.isArray(respData)) {
|
||||||
|
result = respData
|
||||||
|
} else if (respData && Array.isArray(respData.result)) {
|
||||||
|
result = respData.result
|
||||||
|
} else if (respData && respData.data && Array.isArray(respData.data)) {
|
||||||
|
result = respData.data
|
||||||
|
}
|
||||||
|
this.personOptions = result.map((user) => ({
|
||||||
|
userId: user.userId || user.id,
|
||||||
|
username: user.username || user.name,
|
||||||
|
userNumber: user.userNumber || user.userId || user.id
|
||||||
|
})).filter((user) => user.userId && user.userNumber)
|
||||||
|
this.personSearchLoading = false
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('搜索人员失败:', err)
|
||||||
|
this.personOptions = []
|
||||||
|
this.personSearchLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleAddMemberDialogClose() {
|
||||||
|
this.addMemberDialogVisible = false
|
||||||
|
this.addMemberFormData.selectedUsers = []
|
||||||
|
this.personOptions = []
|
||||||
|
},
|
||||||
|
handleAddMemberSubmit() {
|
||||||
|
if (!this.addMemberFormData.selectedUsers || this.addMemberFormData.selectedUsers.length === 0) {
|
||||||
|
this.$message.warning('请选择要添加的成员')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addMemberSubmitting = true
|
||||||
|
// 使用现有接口绑定角色和用户
|
||||||
|
const request = {
|
||||||
|
...api.GET_ROLE_PERMISSION_BING,
|
||||||
|
data: {
|
||||||
|
roleID: this.roleId,
|
||||||
|
userIDs: this.addMemberFormData.selectedUsers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
this.$message.success('添加成员成功')
|
||||||
|
this.addMemberSubmitting = false
|
||||||
|
this.handleAddMemberDialogClose()
|
||||||
|
this.loadMemberList()
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('添加成员失败:', err)
|
||||||
|
this.$message.error('添加成员失败')
|
||||||
|
this.addMemberSubmitting = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteMembers() {
|
||||||
|
const userIds = this.selectedMembers.map((member) => member.userId)
|
||||||
|
// 使用现有接口删除角色用户绑定
|
||||||
|
const request = {
|
||||||
|
...api.DELETE_ROLE_PERMISSION,
|
||||||
|
params: {
|
||||||
|
roleID: this.roleId,
|
||||||
|
userIDs: userIds.join(',')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$request(request)
|
||||||
|
.asyncThen((resp) => {
|
||||||
|
this.$message.success('删除成员成功')
|
||||||
|
this.loadMemberList()
|
||||||
|
})
|
||||||
|
.asyncErrorCatch((err) => {
|
||||||
|
console.error('删除成员失败:', err)
|
||||||
|
this.$message.error('删除成员失败')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.role-member-management-page {
|
||||||
|
.page-header {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-tip {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
.role-name {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.search-section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.pagination-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -215,7 +215,7 @@ export default {
|
|||||||
formatter: this.formatDateTime
|
formatter: this.formatDateTime
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
seqType: '',
|
seqType: 'normal',
|
||||||
seqConfig: {},
|
seqConfig: {},
|
||||||
layout: 'total, prev, pager, next, jumper, sizes'
|
layout: 'total, prev, pager, next, jumper, sizes'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,7 +182,8 @@ export default {
|
|||||||
this.$message.info('下载导入模板功能')
|
this.$message.info('下载导入模板功能')
|
||||||
},
|
},
|
||||||
handleRevert() {
|
handleRevert() {
|
||||||
this.$message.info('退回功能')
|
this.isEditable = true
|
||||||
|
this.$message.success('已进入编辑模式,可修改数据')
|
||||||
},
|
},
|
||||||
handleSave() {
|
handleSave() {
|
||||||
this.$message.info('保存功能')
|
this.$message.info('保存功能')
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import ApaasCustomMyDone from './custom-page/myDone.vue'
|
|||||||
import ApaasCustomMySend from './custom-page/mySend.vue'
|
import ApaasCustomMySend from './custom-page/mySend.vue'
|
||||||
import ApaasCustomCheckPersonPermission from './custom-page/checkPersonPermission.vue'
|
import ApaasCustomCheckPersonPermission from './custom-page/checkPersonPermission.vue'
|
||||||
import ApaasCustomPermissionManagement from './custom-page/permissionManagement.vue'
|
import ApaasCustomPermissionManagement from './custom-page/permissionManagement.vue'
|
||||||
|
import ApaasCustomRoleMemberManagement from './custom-page/roleMemberManagement.vue'
|
||||||
import ApaasCustomLayout from './custom-layout/custom-layout.vue'
|
import ApaasCustomLayout from './custom-layout/custom-layout.vue'
|
||||||
import { customFormComponentList } from './custom-component/form-component'
|
import { customFormComponentList } from './custom-component/form-component'
|
||||||
import { widgetConfigList } from './custom-component/form-config'
|
import { widgetConfigList } from './custom-component/form-config'
|
||||||
@ -48,6 +49,7 @@ const install = function(Vue, opts) {
|
|||||||
Vue.component('apaas-custom-mySend', ApaasCustomMySend)
|
Vue.component('apaas-custom-mySend', ApaasCustomMySend)
|
||||||
Vue.component('apaas-custom-checkPersonPermission', ApaasCustomCheckPersonPermission)
|
Vue.component('apaas-custom-checkPersonPermission', ApaasCustomCheckPersonPermission)
|
||||||
Vue.component('apaas-custom-permissionManagement', ApaasCustomPermissionManagement)
|
Vue.component('apaas-custom-permissionManagement', ApaasCustomPermissionManagement)
|
||||||
|
Vue.component('apaas-custom-roleMemberManagement', ApaasCustomRoleMemberManagement)
|
||||||
Vue.component('apaas-custom-layout', ApaasCustomLayout)
|
Vue.component('apaas-custom-layout', ApaasCustomLayout)
|
||||||
// 安装表单部件
|
// 安装表单部件
|
||||||
// 注册自开发表单组件
|
// 注册自开发表单组件
|
||||||
|
|||||||
@ -45,6 +45,7 @@ Vue.addInterceptorsRequest('REQUEST_PARAMS_INTERCEPTOR', (e) => {
|
|||||||
const authStore = store.state.authModule
|
const authStore = store.state.authModule
|
||||||
if (authStore.token) {
|
if (authStore.token) {
|
||||||
e.headers['xdaptoken'] = authStore.token
|
e.headers['xdaptoken'] = authStore.token
|
||||||
|
// e.headers['xdaptoken'] = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3ODExNTMxMTIsImlhdCI6MTc4MTE0NTkxMiwieGRhcHVzZXJpZCI6IjEwMDc3MTMyNDA5ODk2OTA3NTcxMiJ9.9OKIAqMyTsrQkBSFX3_KcduxVoSe-Tz0cqlKsyNQD1AziiLVGh2w0uK-qu0y6fz916o2Crw8mJWqyrea8oKpdg '
|
||||||
}
|
}
|
||||||
e.headers['xdaptenantid'] = process.env.VUE_APP_TENANT_ID
|
e.headers['xdaptenantid'] = process.env.VUE_APP_TENANT_ID
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user