0.6.0 更新项目、任务成员
This commit is contained in:
parent
e68b6444b1
commit
d45d98661c
|
@ -10,10 +10,11 @@ export function listTask(query) {
|
|||
}
|
||||
|
||||
// 查询任务详细
|
||||
export function getTask(id) {
|
||||
export function getTask(id, receive) {
|
||||
return request({
|
||||
url: '/bst/task/' + id,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params: { receive }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
<template>
|
||||
<div class="avatar-list" v-if="list.length > 0">
|
||||
<div class="avatar-list">
|
||||
<el-tooltip
|
||||
v-for="(item, index) in displayList"
|
||||
:key="item[idProp]"
|
||||
:content="item[showProp]"
|
||||
placement="top"
|
||||
>
|
||||
<div class="avatar-item"
|
||||
:style="{
|
||||
marginLeft: index !== 0 ? `-${size * 0.3}px` : '0',
|
||||
zIndex: list.length - index
|
||||
}"
|
||||
@click="handleClick(item)"
|
||||
>
|
||||
<avatar
|
||||
:size="size"
|
||||
:src="item[avatarProp]"
|
||||
:name="item[showProp]"
|
||||
:char-index="charIndex"
|
||||
/>
|
||||
<div class="avatar-item" :style="listItemStyle(index)" @click="handleClick(item)">
|
||||
<avatar :size="size" :src="item[avatarProp]" :name="item[showProp]" :char-index="charIndex"/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div v-if="enableEdit" class="avatar-item add-btn" :style="listItemStyle(displayList.length)" @click="handleEdit()">
|
||||
<el-avatar :size="size">
|
||||
<i class="el-icon-plus" style="color: #409EFF;" />
|
||||
</el-avatar>
|
||||
</div>
|
||||
|
||||
<!-- 总数显示 -->
|
||||
<el-popover
|
||||
|
@ -67,11 +61,11 @@ export default {
|
|||
},
|
||||
showProp: {
|
||||
type: String,
|
||||
default: 'nickName'
|
||||
default: 'userName'
|
||||
},
|
||||
avatarProp: {
|
||||
type: String,
|
||||
default: 'avatar'
|
||||
default: 'userAvatar'
|
||||
},
|
||||
idProp: {
|
||||
type: String,
|
||||
|
@ -93,6 +87,11 @@ export default {
|
|||
bstType: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
// 是否启用编辑
|
||||
enableEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -104,9 +103,21 @@ export default {
|
|||
return this.list.slice(0, this.maxCount);
|
||||
}
|
||||
return this.list;
|
||||
},
|
||||
// 列表项样式
|
||||
listItemStyle() {
|
||||
return (index) => {
|
||||
return {
|
||||
marginLeft: index !== 0 ? `-${this.size * 0.3}px` : '0',
|
||||
zIndex: this.list.length - index
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleEdit() {
|
||||
this.$emit('edit')
|
||||
},
|
||||
handleClick(item) {
|
||||
if (this.bstType === 'user') {
|
||||
this.$router.push({
|
||||
|
@ -168,6 +179,15 @@ export default {
|
|||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.avatar-item.add-btn {
|
||||
background-color: #fff;
|
||||
border: 2px dotted #409EFF;
|
||||
color: #409EFF;
|
||||
|
||||
&:hover {
|
||||
transform: translateX(30%);
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
border: none;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div>
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" v-show="showSearch" :inline="true" label-width="5em">
|
||||
<el-form-item label="归属部门" prop="deptId">
|
||||
<dept-tree-select v-model="queryParams.deptId" class="small-tree-select" @change="handleQuery"/>
|
||||
<dept-select v-model="queryParams.deptId" check-strictly @change="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="nickName">
|
||||
<el-input
|
||||
|
@ -16,31 +16,6 @@
|
|||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="userName">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="请输入登录账号"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="用户状态"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
|
@ -52,14 +27,16 @@
|
|||
</el-row>
|
||||
|
||||
<el-table
|
||||
size="small"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
v-loading="loadTable"
|
||||
@row-click="changeSelection"
|
||||
@row-dblclick="select"
|
||||
@select-all="selectionAll"
|
||||
@select="changeSelection"
|
||||
@select="handleSelect"
|
||||
highlight-current-row
|
||||
max-height="500px"
|
||||
>
|
||||
<el-table-column align="center" type="selection" v-if="multiple"/>
|
||||
<el-table-column label="#" type="index" align="center"/>
|
||||
|
@ -82,16 +59,7 @@
|
|||
{{d.row.dept == null ? '' : d.row.dept.deptName}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'status'">
|
||||
<dict-tag :value="d.row.status" :options="dict.type.sys_normal_disable"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'employStatus'">
|
||||
<dict-tag :value="d.row.employStatus" :options="dict.type.user_employ_status"/>
|
||||
</template>
|
||||
<template v-else-if="['birthday'].includes(column.key)">
|
||||
{{calcBirthDay(d.row[column.key], new Date()) | dv}} 岁
|
||||
</template>
|
||||
<template v-else-if="['employDate'].includes(column.key)">
|
||||
{{calcFullYear(d.row[column.key], new Date()) | dv}} 年
|
||||
<dict-tag :value="d.row.status" :options="dict.type.user_status"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{d.row[column.key] | dv}}
|
||||
|
@ -109,11 +77,11 @@
|
|||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deepClone } from '@/utils'
|
||||
import DeptTreeSelect from '@/components/Business/Dept/DeptTreeSelect.vue'
|
||||
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue'
|
||||
import BooleanTag from '@/components/BooleanTag/index.vue'
|
||||
import { $showColumns } from '@/utils/mixins'
|
||||
import { listUser } from '@/api/system/user'
|
||||
|
@ -127,8 +95,8 @@ const defaultSort = {
|
|||
export default {
|
||||
name: "UserCheck",
|
||||
mixins: [$showColumns],
|
||||
dicts: ['sys_normal_disable', 'sys_user_sex', 'user_employ_status'],
|
||||
components: {BooleanTag, DeptTreeSelect},
|
||||
dicts: ['user_status'],
|
||||
components: {BooleanTag, DeptSelect},
|
||||
props: {
|
||||
// 标题
|
||||
title: {
|
||||
|
@ -183,11 +151,8 @@ export default {
|
|||
{key: 'userId', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'nickName', visible: true, label: '姓名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'deptId', visible: true, label: '部门', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'userName', visible: true, label: '登录账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'status', visible: true, label: '账号状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'remark', visible: true, label: '备注', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginIp', visible: true, label: '最后登录IP', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginDate', visible: true, label: '最后登录时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
],
|
||||
}
|
||||
|
@ -259,6 +224,9 @@ export default {
|
|||
this.select(this.row);
|
||||
}
|
||||
},
|
||||
handleSelect(selection, row) {
|
||||
this.changeSelection(row);
|
||||
},
|
||||
// 更换某一行的选中状态
|
||||
changeSelection(row){
|
||||
if(this.multiple){
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!--版本更新内容:添加prop属性,修复多选-->
|
||||
|
||||
<template>
|
||||
<el-dialog :title="title" :visible="show" width="80%" top="2vh" @close="close" :append-to-body="true">
|
||||
<el-dialog :title="title" :visible="show" width="900px" top="2vh" @close="close" :append-to-body="true">
|
||||
<user-check
|
||||
v-if="show"
|
||||
ref="check"
|
||||
|
|
143
src/components/Business/User/UserRemoteSelect.vue
Normal file
143
src/components/Business/User/UserRemoteSelect.vue
Normal file
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<el-select
|
||||
v-model="selectedValue"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
filterable
|
||||
:multiple="multiple"
|
||||
:loading="loading"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div class="select-footer">
|
||||
<div style="text-align: center; color: #8492a6; font-size: 13px; line-height: 28px; ">
|
||||
共{{ total }}条数据
|
||||
</div>
|
||||
<el-button v-if="multiple && !isEmpty(options)" style="margin-left: 10px;" size="mini" type="text" @click.stop="handleSelectAll">
|
||||
{{ isAllSelected ? '取消全选' : '全选' }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.userId"
|
||||
:value="item.userId"
|
||||
:label="item.nickName"
|
||||
>
|
||||
<avatar :size="24" :src="item.avatar" :name="item.nickName" :id="item.userId" />
|
||||
<span class="user-name">{{ item.nickName }}</span>
|
||||
</el-option>
|
||||
<el-option v-if="isEmpty(value) && isEmpty(options)" style="display:none" disabled :value="null"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listUser } from '@/api/system/user';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import {isEmpty} from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'UserRemoteSelect',
|
||||
components: {
|
||||
Avatar
|
||||
},
|
||||
props: {
|
||||
// 用户id
|
||||
value: {
|
||||
type: [String, Array],
|
||||
default: null
|
||||
},
|
||||
// 自定义查询参数
|
||||
query: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
// 是否多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
keyword: null
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
// 是否全选
|
||||
isAllSelected() {
|
||||
return this.multiple && this.options.length > 0 && Array.isArray(this.value) && this.value.length === this.options.length;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
query: {
|
||||
handler(nv) {
|
||||
this.queryParams = {
|
||||
...this.queryParams,
|
||||
...nv
|
||||
}
|
||||
this.getOptions();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getOptions();
|
||||
},
|
||||
methods: {
|
||||
isEmpty,
|
||||
// 全选
|
||||
handleSelectAll() {
|
||||
if (this.isAllSelected) {
|
||||
this.handleChange([]);
|
||||
} else {
|
||||
const allUserIds = this.options.map(item => item.userId);
|
||||
this.handleChange(allUserIds);
|
||||
}
|
||||
},
|
||||
handleChange(value) {
|
||||
let list = this.options.filter(item => value.includes(item.userId));
|
||||
this.$emit('change', list);
|
||||
},
|
||||
getOptions() {
|
||||
this.loading = true;
|
||||
this.queryParams = {
|
||||
...this.queryParams,
|
||||
...this.query
|
||||
}
|
||||
listUser(this.queryParams).then(res => {
|
||||
this.options = res.rows;
|
||||
this.total = res.total;
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-footer {
|
||||
padding: 5px 12px;
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.user-name {
|
||||
padding-left: 6px;
|
||||
}
|
||||
</style>
|
75
src/components/CollapsePanel/index.vue
Normal file
75
src/components/CollapsePanel/index.vue
Normal file
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="collapse-title" @click="onChange" >
|
||||
<div class="title-text">{{title}}</div>
|
||||
<el-link type="primary" :underline="false">
|
||||
<template v-if="show">
|
||||
<i class="el-icon-arrow-up"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<i class="el-icon-arrow-down"/>
|
||||
</template>
|
||||
</el-link>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<el-collapse-transition>
|
||||
<div v-show="show">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "CollapsePanel",
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: this.value
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.show = val;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange() {
|
||||
this.show = !this.show;
|
||||
this.$emit('input', this.show);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.collapse-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
background-color: #f4faff;
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: .25s;
|
||||
&:hover {
|
||||
background-color: #e5f2ff;
|
||||
}
|
||||
.title-text {
|
||||
font-size: 14px;
|
||||
color: #1890ff;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -271,14 +271,18 @@ export default {
|
|||
// 新增:鼠标进入处理
|
||||
handleMouseEnter() {
|
||||
if (!this.isListening) {
|
||||
this.$refs.pasteArea.focus();
|
||||
if (this.$refs.pasteArea) {
|
||||
this.$refs.pasteArea.focus();
|
||||
}
|
||||
this.isListening = true;
|
||||
}
|
||||
},
|
||||
// 新增:鼠标离开处理
|
||||
handleMouseLeave() {
|
||||
if (this.isListening) {
|
||||
this.$refs.pasteArea.blur();
|
||||
if (this.$refs.pasteArea) {
|
||||
this.$refs.pasteArea.blur();
|
||||
}
|
||||
this.isListening = false;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,12 +8,12 @@ export const TaskType = {
|
|||
|
||||
// 任务状态
|
||||
export const TaskStatus = {
|
||||
WAIT_COMPLETED: "1", // 待完成(弃用)
|
||||
WAIT_RECEIVE: "1", // 待接收
|
||||
PROCESSING: "2", // 进行中
|
||||
WAIT_CONFIRM: "3", // 待确认(弃用)
|
||||
PASS: "4", // 通过
|
||||
REJECT: "5", // 驳回(弃用)
|
||||
CANCEL: "6", // 取消
|
||||
WAIT_CONFIRM: "3", // 待确认(停用)
|
||||
PASS: "4", // 通过
|
||||
REJECT: "5", // 驳回(停用)
|
||||
CANCEL: "6", // 取消
|
||||
|
||||
// 获取可以提交的任务状态
|
||||
canSubmit() {
|
||||
|
@ -21,11 +21,23 @@ export const TaskStatus = {
|
|||
},
|
||||
// 获取可以取消的任务状态
|
||||
canCancel() {
|
||||
return [this.WAIT_COMPLETED, this.PROCESSING]
|
||||
return [this.WAIT_RECEIVE, this.PROCESSING]
|
||||
},
|
||||
// 获取可以完成的任务状态
|
||||
// 获取可以通过的任务状态
|
||||
canPass() {
|
||||
return [this.PROCESSING]
|
||||
},
|
||||
// 获取可以开始的任务状态
|
||||
canStart() {
|
||||
return [this.WAIT_RECEIVE, this.CANCEL]
|
||||
},
|
||||
// 获取未完成任务状态
|
||||
unComplete() {
|
||||
return [this.PROCESSING]
|
||||
},
|
||||
// 获取已完成任务状态
|
||||
complete() {
|
||||
return [this.PASS]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,3 +154,13 @@ export const Role = {
|
|||
SYS_ADMIN: "sys_admin", // 系统管理员
|
||||
ADMIN: "admin", // 管理员
|
||||
}
|
||||
|
||||
// 项目成员角色
|
||||
export const ProjectMemberRole = {
|
||||
OWNER: "OWNER", // 项目负责人
|
||||
FOLLOWER: "FOLLOWER", // 项目跟进人
|
||||
UI: "UI", // UI设计
|
||||
DEV: "DEV", // 开发
|
||||
QA: "QA", // 测试
|
||||
NORMAL: "NORMAL", // 普通成员
|
||||
}
|
||||
|
|
104
src/views/bst/project/components/ProjectMemberEditDialog.vue
Normal file
104
src/views/bst/project/components/ProjectMemberEditDialog.vue
Normal file
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<el-dialog :visible.sync="dialogVisible" title="编辑成员" width="800px" @open="handleOpen">
|
||||
<el-form :model="form" v-loading="loading" label-position="top" ref="form">
|
||||
<project-member-edit-list :form="form" :rules="rules.memberList" />
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="handleSubmit">保存</el-button>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getProject, updateProject } from '@/api/bst/project';
|
||||
import ProjectMemberEditList from '@/views/bst/project/edit/components/ProjectMemberEditList.vue';
|
||||
export default {
|
||||
name: 'ProjectMemberEditDialog',
|
||||
components: {
|
||||
ProjectMemberEditList
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 项目ID
|
||||
id: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: {
|
||||
memberList: []
|
||||
},
|
||||
rules: {
|
||||
memberList: {
|
||||
userId: [
|
||||
{ required: true, message: "成员不能为空", trigger: "blur" }
|
||||
],
|
||||
role: [
|
||||
{ required: true, message: "角色不能为空", trigger: "change" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleOpen() {
|
||||
if (this.id == null) {
|
||||
this.$message.error('项目ID不能为空');
|
||||
this.dialogVisible = false;
|
||||
return;
|
||||
}
|
||||
this.getDetail();
|
||||
},
|
||||
getDetail() {
|
||||
this.loading = true;
|
||||
getProject(this.id).then(res => {
|
||||
this.form = res.data;
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate().then((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
updateProject({
|
||||
id: this.form.id,
|
||||
memberList: this.form.memberList
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message.success('保存成功');
|
||||
this.dialogVisible = false;
|
||||
this.$emit('success');
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
123
src/views/bst/project/edit/components/ProjectMemberEditList.vue
Normal file
123
src/views/bst/project/edit/components/ProjectMemberEditList.vue
Normal file
|
@ -0,0 +1,123 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
:data="form.memberList"
|
||||
size="mini"
|
||||
stripe
|
||||
:header-cell-style="headerCellStyle"
|
||||
class="mini-table table-form"
|
||||
ref="table"
|
||||
>
|
||||
<el-table-column label="序号" type="index" align="center" width="60" />
|
||||
<table-form-col label="成员" prop-prefix="memberList" prop="userId" required :rules="rules.userId" align="left" width="200">
|
||||
<template slot-scope="d">
|
||||
<avatar :src="d.row.userAvatar" :name="d.row.userName" :char-index="-1" :size="24" />
|
||||
{{d.row.userName}}
|
||||
</template>
|
||||
</table-form-col>
|
||||
<table-form-col label="角色" prop-prefix="memberList" prop="role" required :rules="rules.role">
|
||||
<template slot-scope="d">
|
||||
<el-radio-group v-model="d.row.role" placeholder="请选择角色">
|
||||
<el-radio v-for="item in dict.type.project_member_role" :key="item.value" :label="item.value">
|
||||
{{item.label}}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
</table-form-col>
|
||||
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template #header>
|
||||
<el-button size="small" icon="el-icon-plus" type="text" @click="handleAdd" >新增成员</el-button>
|
||||
</template>
|
||||
<template slot-scope="d">
|
||||
<el-button
|
||||
type="text"
|
||||
@click="handleDel(d.$index, d.row)"
|
||||
icon="el-icon-delete"
|
||||
size="small"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<user-dialog
|
||||
:show.sync="showUserDialog"
|
||||
multiple
|
||||
:query="userQuery"
|
||||
@select="handleSelectUser"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TableFormCol from '@/components/TableFormCol/index.vue'
|
||||
import UserDialog from '@/components/Business/User/UserDialog.vue'
|
||||
import Avatar from '@/components/Avatar/index.vue'
|
||||
import { ProjectMemberRole } from '@/utils/enums'
|
||||
export default {
|
||||
name: "ProjectMemberEditList",
|
||||
dicts: ['project_member_role'],
|
||||
components: { TableFormCol, UserDialog, Avatar},
|
||||
props: {
|
||||
form: {
|
||||
type: Object,
|
||||
default: () =>({
|
||||
memberList: [], // 成员列表
|
||||
})
|
||||
},
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showUserDialog: false,
|
||||
headerCellStyle: {
|
||||
backgroundColor: "#f5f7fa",
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userQuery() {
|
||||
return {
|
||||
excludeUserIds: this.form.memberList.map(item => item.userId),
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 新增行
|
||||
handleAdd() {
|
||||
this.showUserDialog = true;
|
||||
},
|
||||
handleSelectUser(users) {
|
||||
users.forEach(user => {
|
||||
this.form.memberList.push(this.getNewRow(user))
|
||||
})
|
||||
this.showUserDialog = false;
|
||||
},
|
||||
// 获取新的行
|
||||
getNewRow(user) {
|
||||
return {
|
||||
id: null,
|
||||
userId: user.userId,
|
||||
role: ProjectMemberRole.NORMAL,
|
||||
// vo
|
||||
userName: user.nickName,
|
||||
userAvatar: user.avatar,
|
||||
}
|
||||
},
|
||||
// 删除行
|
||||
handleDel(index, row) {
|
||||
this.$confirm(`是否删除成员 【${row.userName}】 ?`, "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.form.memberList.splice(index, 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -5,7 +5,7 @@
|
|||
<el-button type="primary" plain @click="submitForm" icon="el-icon-check" size="small" :loading="submitLoading">提 交</el-button>
|
||||
</edit-header>
|
||||
<div class="app-container">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px" v-loading="loading">
|
||||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px" v-loading="loading">
|
||||
<el-row>
|
||||
<form-col :span="span" label="项目名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入项目名称" />
|
||||
|
@ -31,15 +31,6 @@
|
|||
placeholder="请选择到期时间">
|
||||
</el-date-picker>
|
||||
</form-col>
|
||||
<form-col :span="span" label="负责人" prop="ownerId">
|
||||
<user-select v-model="form.ownerId" />
|
||||
</form-col>
|
||||
<form-col :span="span" label="跟进人" prop="followId">
|
||||
<user-select v-model="form.followId" />
|
||||
</form-col>
|
||||
<form-col :span="span * 2" label="项目成员" prop="memberIds">
|
||||
<user-select v-model="form.memberIds" multiple />
|
||||
</form-col>
|
||||
<form-col :span="24" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</form-col>
|
||||
|
@ -47,6 +38,12 @@
|
|||
<image-upload v-model="form.attaches" :limit="999" :file-type="fileType" edit-name value-type="array-object"/>
|
||||
</form-col>
|
||||
</el-row>
|
||||
|
||||
<el-tabs>
|
||||
<el-tab-pane label="项目成员">
|
||||
<project-member-edit-list :form="form" :rules="rules.memberList" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -60,9 +57,10 @@ import EditHeader from "@/components/EditHeader/index.vue";
|
|||
import CustomerInput from "@/components/Business/Customer/CustomerInput.vue";
|
||||
import UserSelect from "@/components/Business/User/UserSelect.vue";
|
||||
import { FileType } from '@/utils/constants';
|
||||
import ProjectMemberEditList from './components/ProjectMemberEditList.vue';
|
||||
export default {
|
||||
name: "ProjectEdit",
|
||||
components: { FormCol, EditHeader, UserSelect, CustomerInput },
|
||||
components: { FormCol, EditHeader, UserSelect, CustomerInput, ProjectMemberEditList },
|
||||
dicts: ['project_status'],
|
||||
data() {
|
||||
return {
|
||||
|
@ -70,12 +68,22 @@ export default {
|
|||
submitLoading: false,
|
||||
span: 6,
|
||||
// 表单参数
|
||||
form: {},
|
||||
form: {
|
||||
memberList: [],
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "项目名称不能为空", trigger: "blur" }
|
||||
],
|
||||
memberList: {
|
||||
userId: [
|
||||
{ required: true, message: "成员不能为空", trigger: "blur" }
|
||||
],
|
||||
role: [
|
||||
{ required: true, message: "角色不能为空", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
},
|
||||
fileType: FileType.all(),
|
||||
};
|
||||
|
@ -121,7 +129,7 @@ export default {
|
|||
remark: null,
|
||||
attaches: [],
|
||||
customerId: this.$route.query.customerId,
|
||||
memberIds: [],
|
||||
memberList: [],
|
||||
// vo
|
||||
customerName: this.$route.query.customerName,
|
||||
};
|
||||
|
|
|
@ -25,11 +25,8 @@
|
|||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="ownerId">
|
||||
<user-select v-model="queryParams.ownerId" clearable @change="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="跟进人" prop="followId">
|
||||
<user-select v-model="queryParams.followId" clearable @change="handleQuery"/>
|
||||
<el-form-item label="成员" prop="joinUserId">
|
||||
<user-select v-model="queryParams.joinUserId" clearable @change="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发超期" prop="devOverdue">
|
||||
<el-radio-group v-model="queryParams.devOverdue" @change="handleQuery">
|
||||
|
@ -136,6 +133,17 @@
|
|||
<template v-else-if="column.key === 'time'">
|
||||
{{getExpireTime(d.row).value | dv}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'memberList'">
|
||||
<div style="margin: 0 auto; width: fit-content">
|
||||
<avatar-list :list="d.row.memberList" :size="24" :char-index="-1" :max-count="4" unit="人"/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'ownerName' && d.row.memberList != null">
|
||||
{{d.row.memberList.filter(item => item.role === ProjectMemberRole.OWNER).map(item => item.userName).join(",")}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'followName' && d.row.memberList != null">
|
||||
{{d.row.memberList.filter(item => item.role === ProjectMemberRole.FOLLOWER).map(item => item.userName).join(",")}}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{d.row[column.key]}}
|
||||
</template>
|
||||
|
@ -246,7 +254,7 @@
|
|||
<script>
|
||||
import { listProject, delProject, completeProject, acceptProject } from "@/api/bst/project";
|
||||
import { $showColumns } from '@/utils/mixins';
|
||||
import { ProjectStatus } from '@/utils/enums';
|
||||
import { ProjectStatus, ProjectMemberRole } from '@/utils/enums';
|
||||
import FormCol from "@/components/FormCol/index.vue";
|
||||
import ProjectStartDialog from '@/views/bst/project/components/ProjectStartDialog.vue';
|
||||
import ProjectMaintenanceDialog from '@/views/bst/project/components/ProjectMaintenanceDialog.vue';
|
||||
|
@ -256,6 +264,7 @@ import CustomerLink from '@/components/Business/Customer/CustomerLink.vue';
|
|||
import BooleanTag from '@/components/BooleanTag/index.vue';
|
||||
import UserSelect from '@/components/Business/User/UserSelect.vue';
|
||||
import {ProjectUtils} from '@/views/bst/project/utils.js';
|
||||
import AvatarList from '@/components/AvatarList/index.vue';
|
||||
|
||||
export default {
|
||||
name: "Project",
|
||||
|
@ -269,7 +278,8 @@ export default {
|
|||
ProjectLink,
|
||||
CustomerLink,
|
||||
BooleanTag,
|
||||
UserSelect
|
||||
UserSelect,
|
||||
AvatarList
|
||||
},
|
||||
props: {
|
||||
query: {
|
||||
|
@ -287,6 +297,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
ProjectMemberRole,
|
||||
showTaskDialog: false, // 新增任务弹窗
|
||||
ProjectStatus,
|
||||
showStartDialog: false, // 开始开发弹窗
|
||||
|
@ -297,14 +308,15 @@ export default {
|
|||
columns: [
|
||||
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'no', visible: false, label: '项目编号', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
|
||||
{key: 'name', visible: true, label: '项目名称', minWidth: "250", sortable: true, overflow: false, align: 'left', width: null},
|
||||
{key: 'name', visible: true, label: '名称', minWidth: "250", sortable: true, overflow: false, align: 'left', width: null},
|
||||
{key: 'memberList', visible: true, label: '成员', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
|
||||
{key: 'status', visible: false, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'customerName', visible: true, label: '客户', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'expireTime', visible: false, label: '到期时间', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'expectedCompleteDate', visible: false, label: '预计开发', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'maintenanceEndDate', visible: false, label: '运维结束', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'ownerName', visible: true, label: '负责人', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'followName', visible: true, label: '跟进人', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'ownerName', visible: true, label: '负责人', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'followName', visible: true, label: '跟进人', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'amount', visible: false, label: '项目金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'receivedAmount', visible: false, label: '已收金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'operationAmount', visible: false, label: '运维费用', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
|
|
|
@ -106,11 +106,7 @@
|
|||
<el-col :span="6">
|
||||
<!-- 成员 -->
|
||||
<el-card class="box-card" header="项目成员">
|
||||
<el-descriptions :column="2">
|
||||
<el-descriptions-item label="负责人">{{ detail.ownerName | dv}}</el-descriptions-item>
|
||||
<el-descriptions-item label="跟进人">{{ detail.followName | dv}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<avatar-list :list="detail.memberList" :size="32" :char-index="-1"/>
|
||||
<avatar-list :list="detail.memberList" :size="32" :char-index="-1" enable-edit @edit="handleEditMember"/>
|
||||
</el-card>
|
||||
<!-- 附件信息 -->
|
||||
<el-card class="box-card" header="附件">
|
||||
|
@ -150,6 +146,13 @@
|
|||
:id="detail.id"
|
||||
@success="getDetail"
|
||||
/>
|
||||
|
||||
<!-- 编辑成员弹窗 -->
|
||||
<project-member-edit-dialog
|
||||
:visible.sync="editMemberDialogVisible"
|
||||
:id="detail.id"
|
||||
@success="getDetail"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -163,6 +166,8 @@ import ProjectMaintenanceDialog from '@/views/bst/project/components/ProjectMain
|
|||
import AvatarList from '@/components/AvatarList/index.vue';
|
||||
import CustomerLink from '@/components/Business/Customer/CustomerLink.vue';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
import ProjectMemberEditDialog from '@/views/bst/project/components/ProjectMemberEditDialog.vue';
|
||||
|
||||
export default {
|
||||
name: "ProjectView",
|
||||
components: {
|
||||
|
@ -171,7 +176,8 @@ export default {
|
|||
ProjectStartDialog,
|
||||
ProjectMaintenanceDialog,
|
||||
AvatarList,
|
||||
CustomerLink
|
||||
CustomerLink,
|
||||
ProjectMemberEditDialog
|
||||
},
|
||||
dicts: ['project_status'],
|
||||
data() {
|
||||
|
@ -183,7 +189,9 @@ export default {
|
|||
// 支持预览的图片格式
|
||||
imageTypes: ['.png', '.jpg', '.jpeg', '.gif', '.bmp'],
|
||||
// 项目状态
|
||||
ProjectStatus
|
||||
ProjectStatus,
|
||||
// 编辑成员弹窗
|
||||
editMemberDialogVisible: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -210,6 +218,9 @@ export default {
|
|||
this.getDetail();
|
||||
},
|
||||
methods: {
|
||||
handleEditMember() {
|
||||
this.editMemberDialogVisible = true;
|
||||
},
|
||||
checkPermi,
|
||||
// 验收
|
||||
handleAccept(row) {
|
||||
|
|
|
@ -13,24 +13,31 @@
|
|||
<form-col :span="24" label="项目" prop="projectId">
|
||||
<project-select v-model="form.projectId" :disabled="initData.projectId != null" @change="onChangeProject"/>
|
||||
</form-col>
|
||||
<form-col :span="24" label="附件" prop="picture">
|
||||
<form-col :span="24" label="附件" prop="picture">
|
||||
<image-upload v-model="form.picture" :file-type="FileType"/>
|
||||
</form-col>
|
||||
<form-col :span="24" label="类型" prop="type">
|
||||
<form-col :span="span" label="类型" prop="type">
|
||||
<el-radio-group v-model="form.type">
|
||||
<el-radio-button v-for="dict in dict.type.task_type" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
<form-col :span="24" label="优先级" prop="level">
|
||||
<form-col :span="span" label="优先级" prop="level">
|
||||
<el-radio-group v-model="form.level">
|
||||
<el-radio-button v-for="dict in dict.type.task_level" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
<form-col :span="24" label="任务内容" prop="description">
|
||||
<el-input v-model="form.description" placeholder="请输入任务内容" type="textarea" maxlength="1000" show-word-limit/>
|
||||
<el-input v-model="form.description" placeholder="请输入任务内容" type="textarea" maxlength="1000" show-word-limit :autosize="{ minRows: 3, maxRows: 10 }"/>
|
||||
</form-col>
|
||||
<form-col :span="24" label="负责人" prop="ownerIds">
|
||||
<user-select v-model="form.ownerIds" multiple :filter-method="filterOwnerMethod"/>
|
||||
<form-col :span="24" label="负责人" prop="memberList">
|
||||
<user-remote-select
|
||||
:value="userRemoteValue"
|
||||
multiple
|
||||
:init-options="userRemoteInitOptions"
|
||||
@change="onChangeMemberList"
|
||||
:query="userQuery"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="截止时间" prop="expireTime">
|
||||
<el-date-picker clearable
|
||||
|
@ -38,6 +45,7 @@
|
|||
v-model="form.expireTime"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
default-time="23:59:59"
|
||||
placeholder="请选择截止时间">
|
||||
</el-date-picker>
|
||||
</form-col>
|
||||
|
@ -59,10 +67,10 @@ import UserSelect from '@/components/Business/User/UserSelect.vue';
|
|||
import { FileType } from '@/utils/constants';
|
||||
import { checkRole } from '@/utils/permission';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import UserRemoteSelect from '@/components/Business/User/UserRemoteSelect.vue';
|
||||
export default {
|
||||
name: "TaskEditDialog",
|
||||
components: { FormCol, ProjectSelect, UserSelect },
|
||||
components: { FormCol, ProjectSelect, UserSelect, UserRemoteSelect },
|
||||
dicts: ['task_status', 'task_level', 'task_type'],
|
||||
props: {
|
||||
show: {
|
||||
|
@ -84,11 +92,13 @@ export default {
|
|||
loading: false,
|
||||
submitLoading: false,
|
||||
// 表单参数
|
||||
form: {},
|
||||
form: {
|
||||
memberList: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: "任务名称不能为空", trigger: "blur" }
|
||||
description: [
|
||||
{ required: true, message: "任务内容不能为空", trigger: "blur" }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: "类型不能为空", trigger: "change" }
|
||||
|
@ -96,7 +106,7 @@ export default {
|
|||
level: [
|
||||
{ required: true, message: "优先级不能为空", trigger: "change" }
|
||||
],
|
||||
ownerIds: [
|
||||
memberList: [
|
||||
{ required: true, type: 'array', message: "负责人不能为空", trigger: "blur" }
|
||||
],
|
||||
},
|
||||
|
@ -120,48 +130,39 @@ export default {
|
|||
set(value) {
|
||||
this.$emit('update:show', value);
|
||||
}
|
||||
},
|
||||
// 负责人远程选择器值
|
||||
userRemoteValue() {
|
||||
return this.form.memberList.map(item => item.userId);
|
||||
},
|
||||
// 负责人远程选择器初始化选项
|
||||
userRemoteInitOptions() {
|
||||
return this.form.memberList.map(item => {
|
||||
return {
|
||||
userId: item.userId,
|
||||
nickName: item.userName,
|
||||
avatar: item.userAvatar,
|
||||
}
|
||||
});
|
||||
},
|
||||
userQuery() {
|
||||
return {
|
||||
projectId: this.form.projectId
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 过滤可选择的负责人列表
|
||||
* @param {Array} data 用户列表数据
|
||||
* @returns {Array} 过滤后的用户列表
|
||||
*/
|
||||
filterOwnerMethod(data) {
|
||||
// 如果选择了项目,需要判断项目相关人员是否存在
|
||||
if (this.form.projectId) {
|
||||
const { projectOwnerId, projectFollowId, projectMemberIds } = this.form;
|
||||
|
||||
// 项目相关人员信息不完整时返回空数组
|
||||
if (!projectOwnerId || !projectFollowId || !projectMemberIds) {
|
||||
return [];
|
||||
onChangeMemberList(selection) {
|
||||
this.form.memberList = selection.map(item => {
|
||||
return {
|
||||
userId: item.userId,
|
||||
userName: item.nickName
|
||||
}
|
||||
|
||||
// 获取项目相关人员ID列表(负责人、跟进人、成员)
|
||||
const projectUserIds = [
|
||||
projectOwnerId,
|
||||
projectFollowId,
|
||||
...projectMemberIds
|
||||
].filter(Boolean);
|
||||
|
||||
// 过滤出项目相关人员
|
||||
data = data.filter(item => projectUserIds.includes(item.userId));
|
||||
}
|
||||
|
||||
// 非管理员只能选择自己
|
||||
if (!checkRole([Role.SYS_ADMIN, Role.ADMIN])) {
|
||||
data = data.filter(item => item.userId === this.userId);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
},
|
||||
onChangeProject(project) {
|
||||
this.form.projectOwnerId = project.ownerId;
|
||||
this.form.projectFollowId = project.followId;
|
||||
this.form.projectMemberIds = project.memberIds;
|
||||
if (this.form.ownerIds.length > 0) {
|
||||
this.form.ownerIds = [];
|
||||
if (this.form.memberList.length > 0) {
|
||||
this.form.memberList = [];
|
||||
this.$message("由于更换了项目,负责人已清空");
|
||||
}
|
||||
},
|
||||
|
@ -185,7 +186,7 @@ export default {
|
|||
picture: null,
|
||||
description: null,
|
||||
expireTime: null,
|
||||
ownerIds: [],
|
||||
memberList: [],
|
||||
...this.initData
|
||||
};
|
||||
this.resetForm("form");
|
||||
|
|
|
@ -1,48 +1,37 @@
|
|||
<template>
|
||||
<div class="task-process-panel">
|
||||
<el-card class="box-card" header="负责人">
|
||||
<div class="process-list">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24" v-for="owner in ownerList" :key="owner.userId">
|
||||
<div class="process-item">
|
||||
<div class="user-info">
|
||||
<avatar :size="28" :src="owner.avatar" :name="owner.nickName" :id="owner.userId" />
|
||||
<span class="user-name">{{ owner.nickName }}</span>
|
||||
<div class="status-tag">
|
||||
<el-tag size="mini" :type="hasSubmitted(owner.userId) ? 'success' : 'info'">
|
||||
{{ hasSubmitted(owner.userId) ? '已完成' : '未完成' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-info">
|
||||
<div class="info-item">
|
||||
<span class="label">提交数:</span>
|
||||
<span class="value">{{ getSubmitCount(owner.userId) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">通过数:</span>
|
||||
<span class="value">{{ getPassCount(owner.userId) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">通过时间:</span>
|
||||
<span class="value">{{ getFirstPassSubmitTime(owner.userId) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24" v-for="member in memberList" :key="member.id">
|
||||
<div class="process-item">
|
||||
<div class="user-info">
|
||||
<avatar :size="24" :src="member.userAvatar" :name="member.userName" :id="member.userId" :char-index="-1" />
|
||||
<span class="user-name">{{ member.userName }}</span>
|
||||
<div class="status-tag">
|
||||
<dict-tag :value="member.status" :options="dict.type.task_member_status" size="mini" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="process-info">
|
||||
<div class="info-item">
|
||||
<span class="label">接收时间</span>
|
||||
<span class="value">{{member.receiveTime | dv}}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">提交时间</span>
|
||||
<span class="value">{{member.submitTime | dv}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from '@/components/Avatar'
|
||||
import { TaskSubmitStatus } from '@/utils/enums'
|
||||
import { parseTime } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'TaskProcessPanel',
|
||||
dicts: ['task_member_status'],
|
||||
components: {
|
||||
Avatar
|
||||
},
|
||||
|
@ -53,94 +42,60 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
ownerList() {
|
||||
return this.detail.ownerList || []
|
||||
memberList() {
|
||||
return this.detail.memberList || []
|
||||
},
|
||||
submitList() {
|
||||
return this.detail.submitList || []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 获取用户提交次数
|
||||
getSubmitCount(userId) {
|
||||
return this.submitList.filter(item => item.userId === userId).length
|
||||
},
|
||||
// 获取用户通过次数
|
||||
getPassCount(userId) {
|
||||
return this.submitList.filter(item => item.userId === userId && item.status === TaskSubmitStatus.PASS).length
|
||||
},
|
||||
// 获取用户已通过的最早提交时间
|
||||
getFirstPassSubmitTime(userId) {
|
||||
const userPassSubmits = this.submitList.filter(item =>
|
||||
item.userId === userId &&
|
||||
item.status === TaskSubmitStatus.PASS
|
||||
)
|
||||
if (userPassSubmits.length === 0) return '暂未通过'
|
||||
const firstPassSubmit = userPassSubmits.reduce((prev, curr) => {
|
||||
return new Date(prev.createTime) < new Date(curr.createTime) ? prev : curr
|
||||
})
|
||||
return firstPassSubmit.createTime;
|
||||
},
|
||||
// 判断用户是否已完成
|
||||
hasSubmitted(userId) {
|
||||
return this.submitList.some(item =>
|
||||
item.userId === userId &&
|
||||
item.status === TaskSubmitStatus.PASS
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.task-process-panel {
|
||||
.process-list {
|
||||
.process-item {
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
.process-item {
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 4px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
|
||||
.user-name {
|
||||
margin-left: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
|
||||
.user-name {
|
||||
margin-left: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
margin-left: auto;
|
||||
}
|
||||
.status-tag {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.process-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
.process-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
.info-item {
|
||||
font-size: 12px;
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
.info-item {
|
||||
font-size: 12px;
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
|
||||
.label {
|
||||
color: #909399;
|
||||
}
|
||||
.label {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #303133;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.value {
|
||||
color: #303133;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<el-col :span="10">
|
||||
|
||||
<!-- 附件展示 -->
|
||||
<el-card class="card-box" header="任务附件">
|
||||
<el-card class="card-box">
|
||||
<attach-list :file-list="detail.picture" :column="2" />
|
||||
</el-card>
|
||||
|
||||
|
@ -160,7 +160,7 @@ export default {
|
|||
/** 获取详细信息 */
|
||||
getInfo(id) {
|
||||
this.loading = true;
|
||||
getTask(id).then(response => {
|
||||
getTask(id, true).then(response => {
|
||||
this.detail = response.data;
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
|
|
|
@ -14,15 +14,14 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status" v-if="isShow('description')">
|
||||
<el-radio-group v-model="queryParams.status" placeholder="请选择状态" clearable @change="handleQuery">
|
||||
<el-radio-button :label="null">全部</el-radio-button>
|
||||
<el-radio-button
|
||||
<el-form-item label="状态" prop="statusList" v-if="isShow('description')">
|
||||
<el-checkbox-group v-model="queryParams.statusList" placeholder="请选择状态" multiple clearable @change="handleQuery">
|
||||
<el-checkbox-button
|
||||
v-for="dict in dict.type.task_status"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
>{{ dict.label }}</el-checkbox-button>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级" prop="level" v-if="isShow('description')">
|
||||
<el-select v-model="queryParams.level" placeholder="请选择优先级" clearable @change="handleQuery">
|
||||
|
@ -139,9 +138,9 @@
|
|||
截止:{{d.row.expireTime | dv}}<br/>
|
||||
完成:{{d.row.passTime | dv}}<br/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'owner'">
|
||||
<template v-else-if="column.key === 'memberList'">
|
||||
<div style="margin: 0 auto; width: fit-content">
|
||||
<avatar-list :list="d.row.ownerList" :max-count="3" unit="人" :char-index="-1" bst-type="user"/>
|
||||
<avatar-list :list="d.row.memberList" :max-count="3" unit="人" :char-index="-1" bst-type="user"/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
@ -251,10 +250,10 @@ export default {
|
|||
{key: 'description', visible: true, label: '任务内容', minWidth: "350", sortable: false, overflow: false, align: 'left', width: null},
|
||||
{key: 'picture', visible: true, label: '图片', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'projectName', visible: true, label: '项目', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'owner', visible: true, label: '负责人', minWidth: null, sortable: false, overflow: false, align: 'center', width: "150"},
|
||||
{key: 'createName', visible: true, label: '创建人', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'memberList', visible: true, label: '负责人', minWidth: null, sortable: false, overflow: false, align: 'center', width: "150"},
|
||||
{key: 'receivedCount', visible: true, label: '接收', minWidth: null, sortable: false, overflow: false, align: 'center', width: "50"},
|
||||
{key: 'submitCount', visible: true, label: '提交', minWidth: null, sortable: false, overflow: false, align: 'center', width: "50"},
|
||||
{key: 'passCount', visible: true, label: '完成', minWidth: null, sortable: false, overflow: false, align: 'center', width: "50"},
|
||||
{key: 'createName', visible: true, label: '创建人', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'expireTime', visible: true, label: '时间', minWidth: null, sortable: true, overflow: false, align: 'left', width: "190"},
|
||||
],
|
||||
// 排序方式
|
||||
|
@ -289,7 +288,7 @@ export default {
|
|||
projectId: null,
|
||||
name: null,
|
||||
type: null,
|
||||
status: TaskStatus.PROCESSING,
|
||||
statusList: [TaskStatus.PROCESSING, TaskStatus.WAIT_RECEIVE],
|
||||
level: null,
|
||||
createId: null,
|
||||
ownerId: null,
|
||||
|
|
|
@ -9,8 +9,8 @@ export const $task = {
|
|||
return (row) => {
|
||||
return checkPermi(['bst:task:submit'])
|
||||
&& TaskStatus.canSubmit().includes(row.status)
|
||||
&& row.ownerIds != null
|
||||
&& row.ownerIds.includes(this.userId);
|
||||
&& row.memberList != null
|
||||
&& row.memberList.some(item => item.userId === this.userId);
|
||||
}
|
||||
},
|
||||
// 是否可以取消
|
||||
|
@ -45,7 +45,6 @@ export const $task = {
|
|||
// 是否是创建者
|
||||
isCreator() {
|
||||
return (row) => {
|
||||
console.log("isCreator", row, this.userId);
|
||||
return row.createId === this.userId;
|
||||
}
|
||||
}
|
||||
|
|
246
src/views/system/user/components/UserFormDialog.vue
Normal file
246
src/views/system/user/components/UserFormDialog.vue
Normal file
|
@ -0,0 +1,246 @@
|
|||
<template>
|
||||
<el-dialog :title="title" @open="handleOpen" :visible.sync="dialogVisible" width="700px" append-to-body :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="6em" v-loading="loading">
|
||||
<el-row :gutter="12">
|
||||
<form-col :span="24" label="归属部门" prop="deptId">
|
||||
<dept-select v-model="form.deptId" check-strictly/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="姓名" prop="nickName">
|
||||
<el-input v-model="form.nickName" placeholder="请输入姓名" maxlength="30" />
|
||||
</form-col>
|
||||
<form-col :span="span" label="角色">
|
||||
<el-select v-model="form.roleIds" size="small" multiple placeholder="请选择角色" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.roleId"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId"
|
||||
:disabled="item.status == 1"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</form-col>
|
||||
|
||||
<form-col :span="span" label="登录账号" prop="userName">
|
||||
<el-input v-model="form.userName" placeholder="请输入登录账号" maxlength="30" />
|
||||
</form-col>
|
||||
<form-col :span="span" label="登录密码" prop="password" v-if="form.userId == null">
|
||||
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password/>
|
||||
</form-col>
|
||||
</el-row>
|
||||
<el-row :gutter="12">
|
||||
<form-col :span="span" label="手机号码" prop="phonenumber">
|
||||
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
|
||||
</form-col>
|
||||
<form-col :span="span" label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</form-col>
|
||||
<form-col :span="span" label="用户性别">
|
||||
<el-radio-group v-model="form.sex">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.sys_user_sex"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
<form-col :span="span" label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.user_status"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
<form-col :span="span" label="入职日期" prop="employDate">
|
||||
<el-date-picker style="width: 100%" clearable v-model="form.employDate" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="离职日期" prop="resignDate">
|
||||
<el-date-picker style="width: 100%" clearable v-model="form.resignDate" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="身份证正面" prop="idCardFront" label-width="6em">
|
||||
<image-upload v-model="form.idCardFront" :limit="1" :file-size="10" :is-show-tip="false"/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="身份证反面" prop="idCardBack" label-width="6em">
|
||||
<image-upload v-model="form.idCardBack" :limit="1" :file-size="10" :is-show-tip="false"/>
|
||||
</form-col>
|
||||
<form-col :span="span" label="简历" prop="resume">
|
||||
<image-upload v-model="form.resume" :limit="1" :file-size="10" :is-show-tip="false"/>
|
||||
</form-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addUser, getUser, updateUser } from '@/api/system/user'
|
||||
import FormCol from '@/components/FormCol/index.vue'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue'
|
||||
|
||||
export default {
|
||||
name: "UserFormDialog",
|
||||
dicts: ['user_status', 'sys_user_sex'],
|
||||
components: { FormCol, DeptSelect },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 用户ID
|
||||
userId: {
|
||||
type: [Number, String],
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
span: 12,
|
||||
// 部门树选项
|
||||
deptOptions: [],
|
||||
// 岗位选项
|
||||
postOptions: [],
|
||||
// 角色选项
|
||||
roleOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 默认密码
|
||||
initPassword: "",
|
||||
// 表单校验
|
||||
rules: {
|
||||
userNo: [
|
||||
{ required: true, message: "工号不能为空", trigger: "blur" }
|
||||
],
|
||||
userName: [
|
||||
{ required: true, message: "登录账号不能为空", trigger: "blur" },
|
||||
{ min: 2, max: 20, message: '登录账号长度必须介于 2 和 20 之间', trigger: 'blur' }
|
||||
],
|
||||
phonenumber: [
|
||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur"}
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: "归属部门不能为空", trigger: "blur" }
|
||||
],
|
||||
nickName: [
|
||||
{ required: true, message: "姓名不能为空", trigger: "blur" }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
||||
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
|
||||
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
|
||||
],
|
||||
email: [
|
||||
{type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"]}
|
||||
],
|
||||
},
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.form.userId ? "修改用户" : "添加用户";
|
||||
},
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:visible', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getConfigKey("sys.user.initPassword").then(response => {
|
||||
this.initPassword = response.msg;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handleOpen() {
|
||||
this.getUser();
|
||||
},
|
||||
/** 获取用户详情 */
|
||||
getUser() {
|
||||
this.loading = true;
|
||||
getUser(this.userId).then(response => {
|
||||
if (this.userId) {
|
||||
this.form = response.data;
|
||||
this.postOptions = response.posts;
|
||||
this.roleOptions = response.roles;
|
||||
this.$set(this.form, "postIds", response.postIds);
|
||||
this.$set(this.form, "roleIds", response.roleIds);
|
||||
this.form.password = "";
|
||||
} else {
|
||||
this.postOptions = response.posts;
|
||||
this.roleOptions = response.roles;
|
||||
this.reset();
|
||||
this.form.password = this.initPassword;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
userId: null,
|
||||
deptId: null,
|
||||
userName: null,
|
||||
nickName: null,
|
||||
password: null,
|
||||
phonenumber: null,
|
||||
email: null,
|
||||
sex: '2',
|
||||
status: "0",
|
||||
remark: null,
|
||||
birthday: null,
|
||||
employDate: parseTime(new Date(),"{y}-{m}-{d}"),
|
||||
resignDate: null,
|
||||
postIds: [],
|
||||
roleIds: [],
|
||||
idCardFront: null,
|
||||
idCardBack: null,
|
||||
resume: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.userId != null) {
|
||||
this.loading = true;
|
||||
updateUser(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.dialogVisible = false;
|
||||
this.$emit('success');
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
} else {
|
||||
this.loading = true;
|
||||
addUser(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.dialogVisible = false;
|
||||
this.$emit('success');
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 设置部门树选项
|
||||
setDeptOptions(options) {
|
||||
this.deptOptions = options;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,282 +1,195 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!--部门数据-->
|
||||
<el-col :span="4" :xs="24">
|
||||
<div class="head-container">
|
||||
<el-input
|
||||
v-model="deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
size="small"
|
||||
prefix-icon="el-icon-search"
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
</div>
|
||||
<div class="head-container">
|
||||
<el-tree
|
||||
:data="deptOptions"
|
||||
:props="defaultProps"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
ref="tree"
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<!--用户数据-->
|
||||
<el-col :span="20" :xs="24">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="姓名" prop="nickName">
|
||||
<el-input
|
||||
v-model="queryParams.nickName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="userName">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="请输入登录账号"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="用户状态"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="handleQuery"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="info"-->
|
||||
<!-- plain-->
|
||||
<!-- icon="el-icon-upload2"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleImport"-->
|
||||
<!-- v-hasPermi="['system:user:import']"-->
|
||||
<!-- >导入</el-button>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="1.5">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="warning"-->
|
||||
<!-- plain-->
|
||||
<!-- icon="el-icon-download"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleExport"-->
|
||||
<!-- v-hasPermi="['system:user:export']"-->
|
||||
<!-- >导出</el-button>-->
|
||||
<!-- </el-col>-->
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<template v-for="column of showColumns">
|
||||
<el-table-column
|
||||
:key="column.key"
|
||||
:label="column.label"
|
||||
:prop="column.key"
|
||||
:align="column.align"
|
||||
:min-width="column.minWidth"
|
||||
:sort-orders="orderSorts"
|
||||
:sortable="column.sortable"
|
||||
:show-overflow-tooltip="column.overflow"
|
||||
:width="column.width"
|
||||
>
|
||||
<template slot-scope="d">
|
||||
<template v-if="column.key === 'userId'">
|
||||
{{d.row[column.key]}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'deptId'">
|
||||
{{d.row.dept == null ? '' : d.row.dept.deptName}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'status'">
|
||||
<dict-tag :value="d.row.status" :options="dict.type.sys_normal_disable"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'employStatus'">
|
||||
<dict-tag :value="d.row.employStatus" :options="dict.type.user_employ_status"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'roles'">
|
||||
<template v-for="(role, index) in d.row.roles">
|
||||
<el-tag :key="index" v-if="!isEmpty(role.roleName)">{{role.roleName}}</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{d.row[column.key] | dv}}
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="160"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.userId !== '1'">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row)"
|
||||
v-hasPermi="['system:user:query']"
|
||||
>详情</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:user:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>删除</el-button>
|
||||
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
|
||||
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="handleResetPwd" icon="el-icon-key"
|
||||
v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
|
||||
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
|
||||
v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="姓名" prop="nickName">
|
||||
<el-input
|
||||
v-model="queryParams.nickName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="userName">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="请输入登录账号"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="归属部门" prop="deptId">
|
||||
<dept-select
|
||||
v-model="queryParams.deptId"
|
||||
placeholder="请选择归属部门"
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
check-strictly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input
|
||||
v-model="queryParams.phonenumber"
|
||||
placeholder="请输入手机号码"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input
|
||||
v-model="queryParams.email"
|
||||
placeholder="请输入邮箱"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="用户状态"
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.user_status"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="handleQuery"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加或修改用户配置对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="700px" append-to-body :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<form-col :span="24" label="归属部门" prop="deptId">
|
||||
<treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
|
||||
</form-col>
|
||||
<form-col :span="12" label="姓名" prop="nickName">
|
||||
<el-input v-model="form.nickName" placeholder="请输入姓名" maxlength="30" />
|
||||
</form-col>
|
||||
<form-col :span="12" label="角色">
|
||||
<el-select v-model="form.roleIds" multiple placeholder="请选择角色" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.roleId"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId"
|
||||
:disabled="item.status == 1"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</form-col>
|
||||
<form-col :span="12" label="登录账号" prop="userName">
|
||||
<el-input v-model="form.userName" placeholder="请输入登录账号" maxlength="30" />
|
||||
</form-col>
|
||||
<form-col :span="12" label="登录密码" prop="password" v-if="form.userId == null">
|
||||
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password/>
|
||||
</form-col>
|
||||
<form-col :span="12" label="账号状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
<form-col :span="12" label="手机号码" prop="phonenumber">
|
||||
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
|
||||
</form-col>
|
||||
<form-col :span="12" label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</form-col>
|
||||
<form-col :span="12" label="入职日期" prop="birthday">
|
||||
<el-date-picker style="width: 100%" clearable v-model="form.employDate" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"/>
|
||||
</form-col>
|
||||
<form-col :span="12" label="用户性别">
|
||||
<el-radio-group v-model="form.sex">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.sys_user_sex"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</form-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<template v-for="column of showColumns">
|
||||
<el-table-column
|
||||
:key="column.key"
|
||||
:label="column.label"
|
||||
:prop="column.key"
|
||||
:align="column.align"
|
||||
:min-width="column.minWidth"
|
||||
:sort-orders="orderSorts"
|
||||
:sortable="column.sortable"
|
||||
:show-overflow-tooltip="column.overflow"
|
||||
:width="column.width"
|
||||
>
|
||||
<template slot-scope="d">
|
||||
<template v-if="column.key === 'userId'">
|
||||
{{d.row[column.key]}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'deptId'">
|
||||
{{d.row.dept == null ? '' : d.row.dept.deptName}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'status'">
|
||||
<dict-tag :value="d.row.status" :options="dict.type.user_status" size="small"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'roles'">
|
||||
<template v-for="(role, index) in d.row.roles">
|
||||
<el-tag :key="index" v-if="!isEmpty(role.roleName)" size="small" style="margin-right: 4px;">{{role.roleName}}</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{d.row[column.key]}}
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="160"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.userId !== '1'">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row)"
|
||||
v-hasPermi="['system:user:query']"
|
||||
>详情</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:user:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>删除</el-button>
|
||||
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
|
||||
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="handleResetPwd" icon="el-icon-key"
|
||||
v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
|
||||
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
|
||||
v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 用户表单对话框组件 -->
|
||||
<user-form-dialog
|
||||
:visible.sync="open"
|
||||
:userId="userId"
|
||||
@success="getList"
|
||||
ref="userFormDialog"
|
||||
/>
|
||||
|
||||
<!-- 用户导入对话框 -->
|
||||
<import-dialog
|
||||
|
@ -291,30 +204,26 @@
|
|||
|
||||
<script>
|
||||
import {
|
||||
addUser,
|
||||
changeUserStatus,
|
||||
delUser,
|
||||
deptTreeSelect,
|
||||
getUser,
|
||||
listUser,
|
||||
resetUserPwd,
|
||||
updateUser
|
||||
resetUserPwd
|
||||
} from '@/api/system/user'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import FormCol from '@/components/FormCol/index.vue'
|
||||
import { $showColumns } from '@/utils/mixins'
|
||||
import { calcBirthDay, calcFullYear } from '@/utils/date'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import ImportDialog from '@/components/ImportDialog/index.vue'
|
||||
import { isEmpty } from '@/utils/index'
|
||||
import UserFormDialog from './components/UserFormDialog'
|
||||
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue'
|
||||
|
||||
export default {
|
||||
name: "User",
|
||||
mixins: [$showColumns],
|
||||
dicts: ['sys_normal_disable', 'sys_user_sex', 'user_employ_status'],
|
||||
components: {ImportDialog, FormCol, Treeselect },
|
||||
dicts: ['user_status', 'sys_user_sex', 'user_employ_status'],
|
||||
components: {UserFormDialog, ImportDialog, FormCol, DeptSelect },
|
||||
data() {
|
||||
return {
|
||||
// 排序方式
|
||||
|
@ -333,24 +242,16 @@ export default {
|
|||
total: 0,
|
||||
// 用户表格数据
|
||||
userList: null,
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 部门树选项
|
||||
deptOptions: undefined,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 当前编辑的用户ID
|
||||
userId: null,
|
||||
// 部门名称
|
||||
deptName: undefined,
|
||||
// 默认密码
|
||||
initPassword: undefined,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 岗位选项
|
||||
postOptions: [],
|
||||
// 角色选项
|
||||
roleOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 部门树选项
|
||||
deptOptions: undefined,
|
||||
defaultProps: {
|
||||
children: "children",
|
||||
label: "label"
|
||||
|
@ -377,10 +278,10 @@ export default {
|
|||
orderByColumn: "createTime",
|
||||
isAsc: "desc",
|
||||
excludeUserId: 1,
|
||||
userName: undefined,
|
||||
phonenumber: undefined,
|
||||
status: undefined,
|
||||
deptId: undefined
|
||||
userName: null,
|
||||
phonenumber: null,
|
||||
status: null,
|
||||
deptId: null
|
||||
},
|
||||
// 列信息
|
||||
columns: [
|
||||
|
@ -389,38 +290,15 @@ export default {
|
|||
{key: 'userName', visible: true, label: '登录账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'deptName', visible: true, label: '归属部门', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'roles', visible: true, label: '角色', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'status', visible: true, label: '账号状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginIp', visible: true, label: '最后登录IP', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginDate', visible: true, label: '最后登录时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
],
|
||||
// 表单校验
|
||||
rules: {
|
||||
userNo: [
|
||||
{ required: true, message: "工号不能为空", trigger: "blur" }
|
||||
],
|
||||
userName: [
|
||||
{ required: true, message: "登录账号不能为空", trigger: "blur" },
|
||||
{ min: 2, max: 20, message: '登录账号长度必须介于 2 和 20 之间', trigger: 'blur' }
|
||||
],
|
||||
phonenumber: [
|
||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur"}
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: "归属部门不能为空", trigger: "blur" }
|
||||
],
|
||||
nickName: [
|
||||
{ required: true, message: "姓名不能为空", trigger: "blur" }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
||||
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
|
||||
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
|
||||
],
|
||||
email: [
|
||||
{type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"]}
|
||||
],
|
||||
}
|
||||
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'phonenumber', visible: true, label: '手机号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'email', visible: true, label: '邮箱', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginIp', visible: true, label: '登录IP', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'loginDate', visible: true, label: '登录时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'employDate', visible: true, label: '入职日期', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'resignDate', visible: true, label: '离职日期', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
]
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
@ -432,9 +310,6 @@ export default {
|
|||
created() {
|
||||
this.getList();
|
||||
this.getDeptTree();
|
||||
this.getConfigKey("sys.user.initPassword").then(response => {
|
||||
this.initPassword = response.msg;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handleView(row) {
|
||||
|
@ -480,32 +355,6 @@ export default {
|
|||
row.status = row.status === "0" ? "1" : "0";
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
userId: null,
|
||||
deptId: undefined,
|
||||
userName: undefined,
|
||||
nickName: undefined,
|
||||
password: undefined,
|
||||
phonenumber: undefined,
|
||||
email: undefined,
|
||||
sex: '2',
|
||||
status: "0",
|
||||
employStatus: '1',
|
||||
remark: undefined,
|
||||
birthday: null,
|
||||
employDate: parseTime(new Date(),"{y}-{m}-{d}"),
|
||||
postIds: [],
|
||||
roleIds: []
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
|
@ -540,29 +389,13 @@ export default {
|
|||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
getUser().then(response => {
|
||||
this.postOptions = response.posts;
|
||||
this.roleOptions = response.roles;
|
||||
this.open = true;
|
||||
this.title = "添加用户";
|
||||
this.form.password = this.initPassword;
|
||||
});
|
||||
this.userId = null;
|
||||
this.open = true;
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const userId = row.userId || this.ids;
|
||||
getUser(userId).then(response => {
|
||||
this.form = response.data;
|
||||
this.postOptions = response.posts;
|
||||
this.roleOptions = response.roles;
|
||||
this.$set(this.form, "postIds", response.postIds);
|
||||
this.$set(this.form, "roleIds", response.roleIds);
|
||||
this.open = true;
|
||||
this.title = "修改用户";
|
||||
this.form.password = "";
|
||||
});
|
||||
this.userId = row.userId || this.ids;
|
||||
this.open = true;
|
||||
},
|
||||
/** 重置密码按钮操作 */
|
||||
handleResetPwd(row) {
|
||||
|
@ -588,26 +421,6 @@ export default {
|
|||
const userId = row.userId;
|
||||
this.$router.push("/system/user-auth/role/" + userId);
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.userId != undefined) {
|
||||
updateUser(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addUser(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const userIds = row.userId || this.ids;
|
||||
|
@ -618,37 +431,10 @@ export default {
|
|||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('system/user/export', {
|
||||
...this.queryParams
|
||||
}, `user_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.title = "用户导入";
|
||||
this.upload.open = true;
|
||||
},
|
||||
/** 下载模板操作 */
|
||||
importTemplate() {
|
||||
this.download('system/user/importTemplate', {
|
||||
}, `user_template_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true;
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
this.upload.open = false;
|
||||
this.upload.isUploading = false;
|
||||
this.$refs.upload.clearFiles();
|
||||
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
||||
this.getList();
|
||||
},
|
||||
// 提交上传文件
|
||||
submitFileForm() {
|
||||
this.$refs.upload.submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -12,12 +12,19 @@
|
|||
<div class="name">{{ detail.nickName | dv}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<line-field label="手机号" :value="detail.phonenumber" />
|
||||
<line-field label="所属部门" :value="detail.deptName" />
|
||||
<line-field label="账号" :value="detail.userName" />
|
||||
<line-field label="入职时间" :value="detail.employDate" />
|
||||
<line-field label="最后登录IP" :value="detail.loginIp" />
|
||||
<line-field label="最后登录时间" :value="detail.loginDate" />
|
||||
<line-field label="所属部门" :value="detail.deptName" />
|
||||
<line-field label="角色">
|
||||
{{ detail.roles.map(role => role.roleName).join(',') }}
|
||||
</line-field>
|
||||
<line-field label="手机号" :value="detail.phonenumber" />
|
||||
<line-field label="邮箱" :value="detail.email" />
|
||||
<collapse-panel title="更多信息" :value="false">
|
||||
<line-field label="入职时间" :value="detail.employDate" />
|
||||
<line-field label="离职时间" :value="detail.resignDate" />
|
||||
<line-field label="最后登录IP" :value="detail.loginIp" />
|
||||
<line-field label="最后登录时间" :value="detail.loginDate" />
|
||||
</collapse-panel>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
@ -60,6 +67,7 @@ import Project from '@/views/bst/project/index.vue'
|
|||
import Task from '@/views/bst/task/index.vue'
|
||||
import { checkPermi } from '@/utils/permission'
|
||||
import UserStatistics from '@/views/system/user/view/components/UserStatistics'
|
||||
import CollapsePanel from '@/components/CollapsePanel'
|
||||
export default {
|
||||
name: 'UserView',
|
||||
components: {
|
||||
|
@ -68,7 +76,8 @@ export default {
|
|||
Avatar,
|
||||
Project,
|
||||
Task,
|
||||
UserStatistics
|
||||
UserStatistics,
|
||||
CollapsePanel
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue
Block a user