文件调试完成

考核看板初步完成
dev
rdpnr_hemingxia 2025-04-25 18:04:28 +08:00
parent b1251e3bc5
commit b3bd2eff61
11 changed files with 1664 additions and 950 deletions

View File

@ -121,6 +121,11 @@ export default {
type: Array,
default: () => [],
},
isFilter: {
type: Boolean,
default: false,
},
},
data() {
return {
@ -346,7 +351,9 @@ export default {
},
mounted() {
this.fetchTreeData();
if(!this.isFilter){
this.fetchUserList();
}
},
};
</script>

View File

@ -134,7 +134,7 @@ export const systemApi = {
url: '/system/user/deptTree',
method: 'get',
}),
fileUpload: '/common/upload',
fileUpload: process.env.NODE_ENV == 'development' ? '/common/upload' : '/prod-api/common/upload',
downFile: (data) => request({
url: '/common/download',
method: 'get',
@ -145,6 +145,11 @@ export const systemApi = {
method: 'delete',
}),
delFileBatch: (id) => request({
url: `/business/project/file/batch/${id}`,
method: 'delete',
}),
}
@ -195,16 +200,26 @@ export const taskApi = {
url: `/task/${id}`,
method: 'delete',
}),
delTaskModule: (id) => request({
url: `/examine/template/${id}`,
method: 'delete',
}),
getTaskSet: (id) => request({
url: `/task/target/${id}`,
method: 'get',
}),
setTaskSet: (data) => request({
url: `/task/config/update`,
method: 'put',
data: data,
getTaskModel: (data) => request({
url: `/examine/template/list`,
method: 'get',
params: data,
}),
// 获取模板配置
getTaskModelSet: (id) => request({
url: `/examine/template/list/${id}`,
method: 'get',
}),

View File

@ -3,54 +3,25 @@
<div class="topTitle">需求列表</div>
<!-- 搜索筛选区域 -->
<div class="search-filters">
<el-input
v-model="filters.title"
placeholder="请输入"
class="filter-input"
>
<el-input v-model="filters.title" placeholder="请输入" class="filter-input">
<template #prefix>
<div>标题名称</div>
</template>
</el-input>
<el-input
v-model="filters.responsiblePersonName"
placeholder="请选择负责人"
class="filter-input"
readonly
@focus="openUser('search')"
>
<el-input v-model="filters.responsiblePersonName" placeholder="请选择负责人" class="filter-input" readonly
@focus="openUser('search')">
<template #prefix>负责人</template>
</el-input>
<el-select
v-model="filters.demandStatus"
placeholder="不限"
class="filter-select"
clearable
>
<el-select v-model="filters.demandStatus" placeholder="不限" class="filter-select" clearable>
<template #prefix>需求状态</template>
<el-option
v-for="item in statusList"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
<el-option v-for="item in statusList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
</el-select>
<el-select
v-model="filters.priority"
placeholder="不限"
class="filter-select"
clearable
>
<el-select v-model="filters.priority" placeholder="不限" class="filter-select" clearable>
<template #prefix>优先级</template>
<el-option
v-for="item in priorityList"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
<el-option v-for="item in priorityList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
</el-select>
<div class="filter-buttons">
@ -69,13 +40,8 @@
</div>
<!-- 表格区域 -->
<el-table
:data="tableData"
style="width: 100%"
@selection-change="handleSelectionChange"
class="tableBox"
:cell-class-name="setRowClass"
>
<el-table :data="tableData" style="width: 100%" @selection-change="handleSelectionChange" class="tableBox"
:cell-class-name="setRowClass">
<el-table-column type="selection" width="55" />
<el-table-column label="序号" width="70" type="index" />
<el-table-column label="版本号" prop="versionNumber" />
@ -83,48 +49,29 @@
<el-table-column label="需求状态">
<template #default="scope">
<div>
<el-dropdown
trigger="click"
placement="bottom"
:key="scope.row.id"
@command="
<el-dropdown trigger="click" placement="bottom" :key="scope.row.id" @command="
(data) => {
changeRow(data, 'demandStatus', scope.row);
}
"
>
<el-radio
v-model="scope.row.demandStatus"
:label="scope.row.demandStatus"
:class="['status-tag', getStatusClass(scope.row.demandStatus)]"
>
">
<el-radio v-model="scope.row.demandStatus" :label="scope.row.demandStatus"
:class="['status-tag', getStatusClass(scope.row.demandStatus)]">
{{
statusList[scope.row.demandStatus]
? statusList[scope.row.demandStatus].dictLabel
: ""
}}</el-radio
>
}}</el-radio>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item in statusList"
:key="item.dictValue"
:command="item.dictValue"
:class="{
<el-dropdown-item v-for="item in statusList" :key="item.dictValue" :command="item.dictValue" :class="{
tableSelect1: true,
selectedItem1: item.dictValue == scope.row.demandStatus,
}"
><el-radio
v-model="scope.row.demandStatus"
:label="scope.row.demandStatus"
:class="['status-tag', getStatusClass(item.dictValue)]"
>
}"><el-radio v-model="scope.row.demandStatus" :label="scope.row.demandStatus"
:class="['status-tag', getStatusClass(item.dictValue)]">
{{
statusList[item.dictValue]
? statusList[item.dictValue].dictLabel
: ""
}}</el-radio
></el-dropdown-item
>
}}</el-radio></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
@ -152,16 +99,11 @@
<el-table-column label="优先级" prop="priority">
<template #default="scope">
<div>
<el-dropdown
trigger="click"
placement="bottom"
:key="scope.row.id"
@command="
<el-dropdown trigger="click" placement="bottom" :key="scope.row.id" @command="
(data) => {
changeRow(data, 'priority', scope.row);
}
"
>
">
<span class="el-dropdown-link">
{{
priorityList.find(
@ -175,16 +117,10 @@
<i class="el-icon-arrow-down"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item in priorityList"
:key="item.dictValue"
:command="item.dictValue"
:class="{
<el-dropdown-item v-for="item in priorityList" :key="item.dictValue" :command="item.dictValue" :class="{
tableSelect2: true,
selectedItem2: item.dictValue == scope.row.priority,
}"
>{{ item.dictLabel }}</el-dropdown-item
>
}">{{ item.dictLabel }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
@ -196,11 +132,7 @@
<el-button type="text" @click="handleEdit(scope.row)">
编辑
</el-button>
<el-button
type="text"
@click="handleDelete(scope.row)"
style="color: #666"
>
<el-button type="text" @click="handleDelete(scope.row)" style="color: #666">
删除
</el-button>
</div>
@ -211,36 +143,16 @@
<!-- 分页 -->
<div class="pagination">
<span class="total"> {{ total }} </span>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
@current-change="handlePageChange"
/>
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
@current-change="handlePageChange" />
</div>
<SelectUser
:dialogVisible="userSelectDialogVisible"
:multiSelect="false"
:currentSelectedUser="currentSelectedUser"
@confirm="handleUserConfirm"
@close="handleUserClose"
:userIdList="projectUserList"
/>
<el-dialog
:title="!editData.id ? '新建需求' : '修改需求'"
:visible.sync="dialogVisibleAdd"
width="660px"
:close-on-click-modal="false"
>
<el-form
:inline="true"
:rules="rules"
:model="editData"
label-width="80px"
class="addForm"
ref="ruleForm"
v-loading="fileLoading"
>
<SelectUser :dialogVisible="userSelectDialogVisible" :multiSelect="false" :currentSelectedUser="currentSelectedUser"
@confirm="handleUserConfirm" @close="handleUserClose" :userIdList="projectUserList" :isFilter="true"
ref="selectUserRef" />
<el-dialog :title="!editData.id ? '新建需求' : '修改需求'" :visible.sync="dialogVisibleAdd" width="660px"
:close-on-click-modal="false">
<el-form :inline="true" :rules="rules" :model="editData" label-width="80px" class="addForm" ref="ruleForm"
v-loading="fileLoading">
<el-form-item label="标题" class="longItem" prop="title">
<el-input v-model="editData.title"></el-input>
</el-form-item>
@ -248,132 +160,62 @@
<el-input v-model="editData.projectName" disabled></el-input>
</el-form-item>
<el-form-item label="所属版本" prop="versionId">
<el-select
v-model="editData.versionId"
placeholder="请选择所属版本"
clearable
>
<el-option
v-for="item in versionList"
:key="item.nodeId"
:label="item.title"
:value="item.id"
/>
<el-select v-model="editData.versionId" placeholder="请选择所属版本" clearable>
<el-option v-for="item in versionList" :key="item.nodeId" :label="item.title" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="负责人" prop="responsiblePerson">
<el-input
v-model="editData.responsiblePersonName"
placeholder="请选择负责人"
class="filter-input"
readonly
@focus="openUser('add')"
>
<el-input v-model="editData.responsiblePersonName" placeholder="请选择负责人" class="filter-input" readonly
@focus="openUser('add')">
</el-input>
</el-form-item>
<el-form-item label="需求状态" prop="demandStatus">
<el-select
v-model="editData.demandStatus"
placeholder="请选择需求状态"
clearable
>
<el-option
v-for="item in statusList"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
<el-select v-model="editData.demandStatus" placeholder="请选择需求状态" clearable>
<el-option v-for="item in statusList" :key="item.dictValue" :label="item.dictLabel"
:value="item.dictValue" />
</el-select>
</el-form-item>
<el-form-item label="优先级" prop="priority">
<el-select
v-model="editData.priority"
placeholder="请选择优先级"
clearable
>
<el-option
v-for="item in priorityList"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
<el-select v-model="editData.priority" placeholder="请选择优先级" clearable>
<el-option v-for="item in priorityList" :key="item.dictValue" :label="item.dictLabel"
:value="item.dictValue" />
</el-select>
</el-form-item>
<el-form-item label="预计工时" prop="estimatedWorkHours">
<el-select
v-model="editData.estimatedWorkHours"
filterable
allow-create
default-first-option
placeholder="请输入预计工时"
@change="changeTime"
clearable
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
<el-select v-model="editData.estimatedWorkHours" filterable allow-create default-first-option
placeholder="请输入预计工时" @change="changeTime" clearable>
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="开始时间" prop="createTime">
<el-date-picker
@change="changeTime"
v-model="editData.createTime"
type="date"
placeholder="选择日期"
style="width: 200px"
value-format="yyyy-MM-dd 00:00:00"
:picker-options="{
<el-date-picker @change="changeTime" v-model="editData.createTime" type="date" placeholder="选择日期"
style="width: 200px" value-format="yyyy-MM-dd 00:00:00" :picker-options="{
disabledDate: setDateRange,
}"
>
}">
</el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
v-model="editData.endTime"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd 23:59:59"
style="width: 200px"
:picker-options="{
<el-date-picker v-model="editData.endTime" type="date" placeholder="选择日期" value-format="yyyy-MM-dd 23:59:59"
style="width: 200px" :picker-options="{
disabledDate: setDateRange,
}"
>
}">
</el-date-picker>
</el-form-item>
<el-form-item label="附件" class="longItem" prop="endTime">
<el-form-item label="附件" class="longItem" prop="fileList">
<div>
<el-upload
class="upload-demo"
ref="upload"
:action="fileUpload"
:show-file-list="false"
:auto-upload="true"
:multiple="true"
:before-upload="beforeUpload"
:on-success="successUpload"
:headers="{
<el-upload class="upload-demo" ref="upload" :action="fileUpload" :show-file-list="false" :auto-upload="true"
:multiple="true" :before-upload="beforeUpload" :on-success="successUpload" :headers="{
Authorization: 'Bearer ' + token,
}"
:data="{}"
>
}" :data="{}">
<div class="flex-row aic" style="gap: 10px;margin-bottom: 10px;">
<el-button slot="trigger" size="small" type="default" style="width: 200px;color: #333;font-weight: 500;"
>上传附件</el-button
>
<el-button slot="trigger" size="small" type="default"
style="width: 200px;color: #333;font-weight: 500;">上传附件</el-button>
<div slot="tip" style="color: #999999;font-size: 12px;">单个附件限制100M</div>
</div>
</el-upload>
<div class="fileBox">
<div
v-for="(item, index) in editData.fileList"
class="fileRow flex-row jcsb aic"
:key="index"
>
<div v-for="(item, index) in editData.fileList" class="fileRow flex-row jcsb aic" :key="index">
<div class="flex-row aic fileItem">
<img class="" :src="filePng" v-if="getFileType(item.fileName) == 'file'"> </img>
<img class="" :src="imagePng" v-else-if="getFileType(item.fileName) == 'image'"> </img>
@ -518,6 +360,7 @@ export default {
filePng,
zipPng,
imagePng,
delFileArr: []
};
},
watch: {
@ -591,7 +434,7 @@ export default {
this.editData.projectName = this.projectName;
},
handleEdit(row) {
this.editData = row;
this.editData = Object.assign({}, row);
this.editData.projectId = this.projectId;
this.editData.projectName = this.projectName;
this.dialogVisibleAdd = true;
@ -724,30 +567,6 @@ export default {
this.userSelectDialogVisible = false;
},
eidtDemandRow(row, label, old) {
// if (this.checkedRow.demandStatus == 4) {
// this.$confirm("使, ?", "", {
// confirmButtonText: "",
// cancelButtonText: "",
// type: "warning",
// })
// .then(() => {
// demandApi
// .eidtDemand(this.checkedRow)
// .then((res) => {
// this.$message({
// message: "",
// type: "success",
// });
// this.getDemandList();
// })
// .catch((res) => {
// row[label] = old;
// });
// })
// .catch(() => {
// row[label] = old;
// });
// } else {
demandApi
.eidtDemand(this.checkedRow)
.then((res) => {
@ -808,11 +627,17 @@ export default {
this.resetList("add", res.data);
});
}
}
// }
});
},
resetList(type, data) {
async resetList(type, data) {
if (this.delFileArr.length) {
await systemApi.delFileBatch(this.delFileArr.join(','))
this.delFileArr = []
}
let refreshId = "";
if (type == "edit") {
if (this.editData.versionId) {
@ -894,6 +719,7 @@ export default {
res1.data.projectLeader,
...res2.data?.map((ele) => ele.userId),
];
},
setRowClass({ row }) {
if (row.demandStatus == 4) {
@ -924,6 +750,8 @@ export default {
fileUrl: res.url,
});
} else {
this.fileLoading = false;
this.$message({
type: "error",
message: res.msg,
@ -937,15 +765,15 @@ export default {
cancelButtonText: "取消",
type: "warning",
}).then(() => {
systemApi.delFile(row.id).then((res) => {
this.editData.fileList = this.editData.fileList.filter(
(ele) => ele.fileNewName != row.fileNewName
);
this.delFileArr.push(row.id)
this.$message({
type: 'success',
message: "删除成功!"
})
});
});
} else {
this.editData.fileList = this.editData.fileList.filter(
@ -1023,6 +851,7 @@ export default {
padding-left: 5px !important;
}
}
::v-deep .status-tag .el-radio__inner {
height: 18px !important;
width: 18px !important;
@ -1030,41 +859,53 @@ export default {
text-align: center;
margin-bottom: 1px;
background: #fff !important;
&::after {
height: 10px;
width: 10px;
}
}
::v-deep .status-tag.pending .el-radio__inner {
border-color: #ff7d00;
&::after {
background-color: #ff7d00 !important;
}
}
::v-deep .status-tag.in-progress .el-radio__inner {
border-color: #4096ff !important;
&::after {
background-color: #4096ff !important;
}
}
::v-deep .status-tag.completed .el-radio__inner {
border-color: #50b6aa !important;
&::after {
background-color: #50b6aa !important;
}
}
::v-deep .status-tag.closed .el-radio__inner {
border-color: #ccc !important;
&::after {
background-color: #ccc !important;
}
}
::v-deep .status-tag.wait .el-radio__inner {
border-color: #999 !important;
&::after {
background-color: #999 !important;
}
}
::v-deep .status-tag.pending .el-radio__label {
color: #ff7d00 !important;
// background-color: #fff7e6;
@ -1084,9 +925,11 @@ export default {
color: #999 !important;
// background-color: #f5f5f5;
}
::v-deep .status-tag.closed .el-radio__label {
color: #ccc !important;
}
.pagination {
margin-top: 20px;
display: flex;
@ -1099,8 +942,10 @@ export default {
font-size: 16px;
font-weight: 600;
}
::v-deep .disabled.el-table__cell {
color: #ccc;
.el-dropdown-link {
color: #ccc;
}
@ -1131,12 +976,15 @@ export default {
padding-left: 10px !important;
font-weight: 600;
}
.search-filters ::v-deep .el-input__inner {
padding-left: 80px !important;
::placeholder {
color: #bbb;
}
}
::v-deep .el-button--primary {
background-color: #4096ff;
}
@ -1145,35 +993,44 @@ export default {
border-color: #4096ff;
background-color: #4096ff;
}
::v-deep .addForm {
.el-input__inner {
// width: 100%;
width: 200px;
}
.el-form-item {
width: 48%;
}
.el-input--prefix .el-input__inner {
padding-left: 40px;
}
}
::v-deep .longItem {
width: 100% !important;
.el-form-item__content {
width: 82.2%;
.el-input__inner {
width: 100%;
}
}
}
.tableSelect1 {
width: 150px;
text-align: left !important;
}
.tableSelect2 {
width: 100px;
text-align: left !important;
}
.selectedItem1 {
&::after {
content: "✔";
@ -1184,9 +1041,11 @@ export default {
color: #4096ff;
}
}
.selectedItem2 {
color: #4096ff;
position: relative;
&::after {
content: "✔";
width: 10px;
@ -1196,17 +1055,20 @@ export default {
color: #4096ff;
}
}
.tableBox {
.el-radio {
margin-left: 0;
}
}
.topTitle {
padding: 0 20px 20px;
font-size: 18px;
font-weight: 600;
color: #333;
}
.fileRow {
height: 38px;
padding: 0 10px;
@ -1218,14 +1080,17 @@ export default {
font-size: 16px;
cursor: pointer;
}
img {
height: 18px;
}
}
.fileItem {
gap: 10px;
cursor: pointer;
}
.fileBox {
max-height: 200px;
overflow: auto;

View File

@ -65,11 +65,22 @@
class="nodeIcon"
/>
<!-- 节点文本 -->
<span
:class="['nodeLabel', data.nodeId === selectedId ? 'selected' : '']"
<el-tooltip
class="item"
effect="light"
:content="data.title"
placement="top"
:disabled="data.title.length > 8 ? false : true"
>
<div
:class="[
'nodeLabel',
data.nodeId === selectedId ? 'selected' : '',
]"
>
{{ data.title }}
</span>
</div>
</el-tooltip>
<!-- 右侧数字标记 -->
<span
@ -164,7 +175,7 @@ export default {
})
.then((res) => {
if (!res.data.length) {
this.treeData=[]
this.treeData = [];
return;
}
res.data = res.data.map((ele) => {
@ -221,6 +232,13 @@ export default {
});
return;
}
if (this.demandData.name.length > 10) {
this.$message({
message: "版本号限制10个字符",
type: "warning",
});
return;
}
let param = {
projectId: this.projectId,
versionNumber: this.demandData.name,
@ -348,6 +366,11 @@ export default {
font-weight: 600;
line-height: 36px;
color: #333;
max-width: 160px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding-right: 20px;
}
.nodeLabel.selected {

View File

@ -1,119 +1,61 @@
<template>
<div class="project-management"
v-loading="fileLoading"
>
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="120px"
class="custom-form"
>
<div class="project-management" v-loading="fileLoading">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px" class="custom-form">
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="项目名称" prop="projectName">
<div>
<el-input
v-model="formData.projectName"
placeholder="请输入项目名称"
:disabled="isEditing"
class="full-width longInput"
/>
<el-input v-model="formData.projectName" placeholder="请输入项目名称" :disabled="isEditing"
class="full-width longInput" />
</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目编码" prop="projectCode">
<el-input
v-model="formData.projectCode"
class="full-width"
:disabled="isEditing"
/>
<el-input v-model="formData.projectCode" class="full-width" :disabled="isEditing" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目负责人" prop="projectLeader">
<el-input
v-model="formData.projectLeaderName"
placeholder="选择项目负责人"
readonly
:disabled="isEditing"
@click.native="openProjectManagerSelect"
>
<el-button
size="mini"
slot="append"
icon="el-icon-s-custom"
></el-button
></el-input>
<el-input v-model="formData.projectLeaderName" placeholder="选择项目负责人" readonly :disabled="isEditing"
@click.native="openProjectManagerSelect">
<el-button size="mini" slot="append" icon="el-icon-s-custom"></el-button></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="数据状态" prop="dataState" style="display: none">
<el-select
v-model="formData.dataState"
placeholder="根据时间自动生成"
disabled
class="full-width"
>
<el-select v-model="formData.dataState" placeholder="根据时间自动生成" disabled class="full-width">
<el-option label="未启动" value="0" />
<el-option label="进行中" value="1" />
<el-option label="已完成" value="2" />
</el-select>
</el-form-item>
<el-form-item label="项目状态" prop="projectState">
<el-select
v-model="formData.projectState"
placeholder="请选择项目状态"
class="full-width"
>
<el-option
v-for="item in statusList"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
<el-select v-model="formData.projectState" placeholder="请选择项目状态" class="full-width">
<el-option v-for="item in statusList" :key="item.dictValue" :label="item.dictLabel"
:value="item.dictValue" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计人天" prop="budgetDate">
<el-input
v-model.number="formData.budgetDate"
:min="0"
:disabled="isEditing"
class="full-width"
/>
<el-input v-model.number="formData.budgetDate" :min="0" :disabled="isEditing" class="full-width" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="开始日期" prop="startDate">
<el-date-picker
v-model="formData.startDate"
type="date"
placeholder="选择开始日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
class="full-width"
:disabled="isEditing"
/>
<el-date-picker v-model="formData.startDate" type="date" placeholder="选择开始日期" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" class="full-width" :disabled="isEditing" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束日期" prop="endDate">
<el-date-picker
v-model="formData.endDate"
type="date"
placeholder="选择结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
class="full-width"
:disabled="isEditing"
/>
<el-date-picker v-model="formData.endDate" type="date" placeholder="选择结束日期" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" class="full-width" :disabled="isEditing" />
</el-form-item>
</el-col>
</el-row>
@ -121,33 +63,18 @@
<el-col :span="24">
<el-form-item label="附件" prop="fileList">
<div>
<el-upload
class="upload-demo"
ref="upload"
:action="fileUpload"
:show-file-list="false"
:auto-upload="true"
:multiple="true"
:before-upload="beforeUpload"
:on-success="successUpload"
:headers="{
<el-upload class="upload-demo" ref="upload" :action="fileUpload" :show-file-list="false"
:auto-upload="true" :multiple="true" :before-upload="beforeUpload" :on-success="successUpload" :headers="{
Authorization: 'Bearer ' + token,
}"
:data="{}"
>
}" :data="{}">
<div class="flex-row aic" style="gap: 10px;margin-bottom: 10px;">
<el-button slot="trigger" size="small" type="default" style="width: 200px;color: #333;font-weight: 500;"
>上传附件</el-button
>
<el-button slot="trigger" size="small" type="default"
style="width: 200px;color: #333;font-weight: 500;">上传附件</el-button>
<div slot="tip" style="color: #999999;font-size: 12px;">单个附件限制100M</div>
</div>
</el-upload>
<div class="fileBox">
<div
v-for="(item, index) in formData.fileList"
class="fileRow flex-row jcsb aic"
:key="index"
>
<div v-for="(item, index) in formData.fileList" class="fileRow flex-row jcsb aic" :key="index">
<div class="flex-row aic fileItem">
<img class="" :src="filePng" v-if="getFileType(item.fileName) == 'file'"> </img>
<img class="" :src="imagePng" v-else-if="getFileType(item.fileName) == 'image'"> </img>
@ -163,59 +90,29 @@
</el-row>
</el-form>
<div class="form-actions jcc" v-show="!isEditing">
<el-button
type="primary"
@click="saveProject"
v-hasPermi="['project:detail:save']"
>保存</el-button
>
<el-button type="primary" @click="saveProject" v-hasPermi="['project:detail:save']"></el-button>
<el-button @click="cancelEdit"></el-button>
</div>
<div class="userBox">
<div class="table-actions">
<el-button
type="primary"
@click="addUser"
v-hasPermi="['project:detail:addUser']"
>新增成员</el-button
>
<el-button type="primary" @click="addUser" v-hasPermi="['project:detail:addUser']"></el-button>
</div>
<div class="f1">
<CustomTable
:columns="columns"
:tableData="tableData"
:show-selection="false"
:show-index="true"
:show-pagination="false"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
style="height: 100%"
>
<CustomTable :columns="columns" :tableData="tableData" :show-selection="false" :show-index="true"
:show-pagination="false" @size-change="handleSizeChange" @current-change="handleCurrentChange"
style="height: 100%">
<template slot="userName" slot-scope="{ row }">
<el-input
v-if="row.isNew"
v-model="row.userName"
placeholder="选择人员"
readonly
@click.native="openSelectUser(row)"
/>
<el-input v-if="row.isNew" v-model="row.userName" placeholder="选择人员" readonly
@click.native="openSelectUser(row)" />
<span v-else>{{ row.userName }}</span>
</template>
<template slot="post" slot-scope="{ row }">
<el-select
v-if="
<el-select v-if="
(row.isEditing === true && row.teamId == row.teamId) ||
row.isNew
"
v-model="row.postId"
placeholder="请选择职位"
>
<el-option
v-for="post in postOptions"
:key="post.dictValue"
:label="post.dictLabel"
:value="post.dictValue"
/>
" v-model="row.postId" placeholder="请选择职位">
<el-option v-for="post in postOptions" :key="post.dictValue" :label="post.dictLabel"
:value="post.dictValue" />
</el-select>
<span v-else>{{
postOptions.find((post) => post.dictValue === row.postId)
@ -227,59 +124,20 @@
<template slot="operation" slot-scope="{ row }">
<div class="operation-buttons">
<template v-if="row.isNew">
<el-button
text
type="text"
size="mini"
@click="confirmAddUser(row)"
>确认</el-button
>
<el-button
text
type="text"
size="mini"
@click="cancelAddUser(row)"
>取消</el-button
>
<el-button text type="text" size="mini" @click="confirmAddUser(row)"></el-button>
<el-button text type="text" size="mini" @click="cancelAddUser(row)"></el-button>
</template>
<template v-else-if="row.isEditing && row.teamId == row.teamId">
<el-button
text
type="text"
size="mini"
@click="saveUserEdit(row)"
>保存</el-button
>
<el-button
text
type="text"
size="mini"
@click="cancelUserEdit(row)"
>取消</el-button
>
<el-button text type="text" size="mini" @click="saveUserEdit(row)"></el-button>
<el-button text type="text" size="mini" @click="cancelUserEdit(row)"></el-button>
</template>
<template v-else>
<el-button
type="text"
size="mini"
v-hasPermi="['project:detail:editUser']"
@click="editUser(row)"
>编辑</el-button
>
<el-button
type="text"
size="mini"
v-hasPermi="['project:detail:workLog']"
@click="showTimesheet(row)"
>工作日志</el-button
>
<el-button
type="text"
size="mini"
v-hasPermi="['project:detail:deleteUser']"
@click="confirmDelete(row)"
>删除</el-button
>
<el-button type="text" size="mini" v-hasPermi="['project:detail:editUser']"
@click="editUser(row)">编辑</el-button>
<el-button type="text" size="mini" v-hasPermi="['project:detail:workLog']"
@click="showTimesheet(row)">工作日志</el-button>
<el-button type="text" size="mini" v-hasPermi="['project:detail:deleteUser']"
@click="confirmDelete(row)">删除</el-button>
</template>
</div>
</template>
@ -287,21 +145,12 @@
</div>
</div>
<SelectUser
:dialogVisible="showSelectUser"
:multi-select="false"
:currentSelectedUser="currentSelectedUser"
@confirm="handleUserConfirm"
@close="closeSelectUser"
/>
<SelectUser :dialogVisible="showSelectUser" :multi-select="false" :currentSelectedUser="currentSelectedUser"
@confirm="handleUserConfirm" @close="closeSelectUser" />
<SelectUser
:dialogVisible="showProjectManagerSelect"
:multi-select="false"
:currentSelectedUser="projectManagerSelectedUser"
@confirm="handleProjectManagerConfirm"
@close="closeProjectManagerSelect"
/>
<SelectUser :dialogVisible="showProjectManagerSelect" :multi-select="false"
:currentSelectedUser="projectManagerSelectedUser" @confirm="handleProjectManagerConfirm"
@close="closeProjectManagerSelect" />
</div>
</template>
@ -378,13 +227,14 @@ export default {
{ required: true, message: "预算天数为必填", trigger: "blur" },
],
fileList: [
{ required: true, message: "预算天数为必填", trigger: "blur" },
{ required: true, message: "附件为必填", trigger: "blur" },
],
},
filePng,
zipPng,
imagePng,
token: getToken(),
delFileArr: []
};
},
@ -450,6 +300,8 @@ export default {
this.formData.projectId = res.data.projectId;
this.formData.projectCode = res.data.projectCode;
this.$modal.msgSuccess("操作成功");
this.fetchProjectData()
} else {
const hasLog = await projectApi.projectHasLogData({
projectId: this.formData.projectId,
@ -463,9 +315,22 @@ export default {
)
.then(async () => {
await projectApi.updateProject(projectDataToSave);
if (this.delFileArr.length) {
await systemApi.delFileBatch(this.delFileArr.join(','))
this.delFileArr = []
}
this.fetchProjectData()
});
} else {
await projectApi.updateProject(projectDataToSave);
if (this.delFileArr.length) {
await systemApi.delFileBatch(this.delFileArr.join(','))
this.delFileArr = []
}
this.fetchProjectData()
this.$modal.msgSuccess("操作成功");
}
}
@ -623,7 +488,7 @@ export default {
},
async fetchProjectData(id) {
try {
const response = await projectApi.getProjectDetail(id);
const response = await projectApi.getProjectDetail(id||this.formData.projectId);
const projectData = response.data;
let {
projectId,
@ -693,6 +558,7 @@ export default {
}
},
beforeUpload(file) {
this.fileLoading = true;
if (file.size > 1024 * 1024 * 100) {
this.fileLoading = false;
@ -716,6 +582,7 @@ export default {
fileUrl: res.url,
});
} else {
this.fileLoading = false;
this.$message({
type: "error",
message: res.msg,
@ -729,7 +596,7 @@ export default {
cancelButtonText: "取消",
type: "warning",
}).then(() => {
systemApi.delFile(row.id).then((res) => {
this.delFileArr.push(row.id)
this.formData.fileList = this.formData.fileList.filter(
(ele) => ele.fileNewName != row.fileNewName
);
@ -738,7 +605,6 @@ export default {
message: "删除成功!"
})
});
});
} else {
this.formData.fileList = this.formData.fileList.filter(
(ele) => ele.fileNewName != row.fileNewName
@ -817,7 +683,8 @@ export default {
}
.custom-form ::v-deep .el-form-item {
margin-bottom: 25px; /* 增加表单行间距 */
margin-bottom: 25px;
/* 增加表单行间距 */
}
.custom-form ::v-deep .el-form-item__content {
@ -826,24 +693,29 @@ export default {
}
.custom-form ::v-deep .el-input {
height: 42px; /* 调高输入框高度 */
height: 42px;
/* 调高输入框高度 */
width: 80%;
}
::v-deep .el-form-item__label {
height: 42px; /* 调高输入框高度 */
height: 42px;
/* 调高输入框高度 */
line-height: 42px;
}
.custom-form ::v-deep .el-input__wrapper,
.custom-form ::v-deep .el-date-editor.el-input,
.custom-form ::v-deep .el-input-number {
height: 42px; /* 调高输入框高度 */
height: 42px;
/* 调高输入框高度 */
width: 80%;
}
.custom-form ::v-deep .el-input__inner {
height: 100%;
}
.custom-form ::v-deep .el-select {
width: 100%;
}
@ -855,12 +727,14 @@ export default {
display: flex;
flex-direction: column;
}
.userBox {
width: 100%;
display: flex;
flex-direction: column;
flex: 1;
}
.table-actions {
width: 100%;
display: flex;
@ -927,12 +801,14 @@ export default {
height: 64px;
margin-bottom: 16px;
}
.fileRow {
height: 38px;
padding: 0 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
img {
height: 18px;
}
@ -942,12 +818,14 @@ export default {
cursor: pointer;
}
}
.fileItem {
gap: 10px;
cursor: pointer;
}
.fileBox {
max-height: 200px;
max-height: 136px;
overflow: auto;
padding-right: 10px;
max-width: 90%;

View File

@ -237,6 +237,8 @@ export default {
.selectBox span {
width: 120px;
}
.content{
::v-deep .el-table {
height: 100% !important;
}
@ -318,4 +320,6 @@ export default {
::v-deep .el-table__footer td {
border: none !important;
}
}
</style>

View File

@ -6,21 +6,14 @@
{{ examineTask.taskName }}
</div>
<div class="flex-row jcfs f1" style="gap: 20px" v-if="isEdit">
<el-button type="default" style="width: 90px" @click="saveScoreCheck(0)"
>保存</el-button
>
<el-button type="primary" style="width: 90px" @click="saveScoreCheck(1)"
>提交</el-button
>
<el-button type="default" style="width: 90px" @click="saveScoreCheck(0)"></el-button>
<el-button type="primary" style="width: 90px" @click="saveScoreCheck(1)"></el-button>
</div>
</div>
<div class="flex-row jcsb aic userBox headerBox">
<div class="flex-row aic" style="width: 200px;">
<i
class="el-icon-user-solid"
style="color: #4096ff; font-size: 24px; margin-right: 5px"
></i
>{{ examineUser.userName }}
<i class="el-icon-user-solid" style="color: #4096ff; font-size: 24px; margin-right: 5px"></i>{{
examineUser.userName }}
</div>
<div class="totalBox aic" v-if="!isNormal">
<div>考核评分</div>
@ -28,93 +21,64 @@
</div>
</div>
<div class="tableBox">
<div
class="tableRow"
v-for="(table, index) in tableData"
:key="index"
style="margin-bottom: 20px"
>
<div class="tableRow" v-for="(table, index) in tableData" :key="index" style="margin-bottom: 20px">
<div class="userBox">{{ table[0].reviewCategory }}</div>
<el-table :data="table" style="width: 100%">
<el-table-column
v-for="(header, hIndex) in headers"
:key="hIndex"
:label="header.label"
:prop="header.prop"
:width="header.width"
:minWidth="header.minWidth"
>
<el-table-column v-for="(header, hIndex) in headers" :key="hIndex" :label="header.label" :prop="header.prop"
:width="header.width" :minWidth="header.minWidth">
</el-table-column>
<el-table-column
label="评分"
prop="score"
:minWidth="isNormal ? 320 : 420"
class-name="sorceTableCell"
>
<el-table-column class-name="editCell" label="员工自评" prop="score"
v-if="!isNormal && examineTask.templateId && table[0].reviewCategory == '发展与协作' && examineTask.templateType != 0"
min-width="220">
<template slot-scope="scope">
<div>
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="0/300" v-model="scope.row.remark"
readonly maxlength="300" show-word-limit>
</el-input>
</div>
</template>
</el-table-column>
<el-table-column label="评分" prop="score"
:minWidth="isNormal ? 320 : table[0].reviewCategory == '发展与协作' ? 220 : 420" class-name="sorceTableCell"
v-if="(isNormal && table[0].reviewCategory != '发展与协作') || !isNormal">
<template slot-scope="scope">
<div style="width: 88%; position: relative">
<div>
<div
class="flex-row jcsb"
style="
<div class="flex-row jcsb" style="
margin-left: 10px;
width: 90%;
color: #999;
font-weight: 500;
font-size: 14px;
"
>
">
<div>0</div>
<div v-show="scope.row.score != 10">10</div>
</div>
<div
class="scoreText aic"
v-show="scope.row.score != 0"
:style="{
<div class="scoreText aic" v-show="scope.row.score != 0" :style="{
left: scope.row.score * 9 - 5 + '%',
}"
>
<img
src="@/assets/task/score.png"
:style="{
}">
<img src="@/assets/task/score.png" :style="{
height: '28px',
width: '34px',
zIndex: 0,
position: 'absolute',
top: '0',
}"
alt=""
/>
<div
:style="{
}" alt="" />
<div :style="{
zIndex: 10,
paddingLeft: scope.row.score != 10 ? '13px' : '9px',
}"
>
}">
{{ scope.row.score }}
</div>
</div>
<div
v-for="item in scope.row.score == 0
<div v-for="item in scope.row.score == 0
? 0
: scope.row.score - 1"
:key="item"
class="stepBox"
:style="{
: scope.row.score - 1" :key="item" class="stepBox" :style="{
left: item * 9 + 1.5 + '%',
}"
></div>
<el-slider
v-model="scope.row.score"
:min="0"
:max="10"
@change="updateScore(scope.row)"
:disabled="!isEdit"
style="width: 90%"
show-stops
show-tooltip
></el-slider>
}"></div>
<el-slider v-model="scope.row.score" :min="0" :max="10" @change="updateScore(scope.row)"
:disabled="!isEdit" style="width: 90%" show-stops show-tooltip></el-slider>
</div>
<div class="statusText" v-show="scope.row.score == 0">
暂未打分
@ -122,49 +86,38 @@
</div>
</template>
</el-table-column>
<el-table-column class-name="editCell" label="自评总结" prop="score" v-if="isNormal" minWidth="140">
<el-table-column class-name="editCell" label="自评总结" prop="score"
v-if="(isNormal && examineTask.templateId && table[0].reviewCategory == '发展与协作') || (isNormal && !examineTask.templateId)"
minWidth="140">
<template slot-scope="scope">
<div>
<el-button
v-if="isEdit"
@click="handleEdit(scope.row)"
type="text"
size="mini"
:class="{ hasEdit: !scope.row.remark }"
style="font-weight: 600"
>{{ scope.row.remark ? "查看" : "暂未评价" }}
<i
style="color: #4096ff; font-size: 14px"
class="el-icon-edit el-icon--right"
></i
></el-button>
<el-button
v-if="!isEdit"
@click="handleEdit(scope.row)"
type="text"
size="mini"
:class="{ hasEdit: !scope.row.remark }"
style="font-weight: 600"
>{{ scope.row.remark ? "查看" : "暂未评价" }}</el-button
>
<el-button v-if="isEdit" @click="handleEdit(scope.row)" type="text" size="mini"
:class="{ hasEdit: !scope.row.remark }" style="font-weight: 600">{{ scope.row.remark ? "查看" : "暂未评价"
}}
<i style="color: #4096ff; font-size: 14px" class="el-icon-edit el-icon--right"></i></el-button>
<el-button v-if="!isEdit" @click="handleEdit(scope.row)" type="text" size="mini"
:class="{ hasEdit: !scope.row.remark }" style="font-weight: 600">{{ scope.row.remark ? "查看" : "暂未评价"
}}</el-button>
</div>
</template>
</el-table-column>
</el-table>
<div v-if="examineTask.templateType != 0 && isNormal && table[0].reviewCategory != ''"
style="margin-top: 10px;">
<div class="userBox">评价</div>
<div>
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="0/300" v-model="table[0].remarkCate"
:readonly="!isEdit" maxlength="300" show-word-limit>
</el-input>
</div>
</div>
</div>
<div>
<div v-if="!isNormal">
<div v-if="(isNormal && examineTask.templateType == 0) || (!isNormal)">
<div class="userBox">总体评价</div>
<div>
<el-input
type="textarea"
:autosize="{ minRows: 4 }"
placeholder="0/300"
v-model="saveData.judgeContent"
:readonly="!isEdit"
maxlength="300"
show-word-limit
>
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="0/300" v-model="saveData.judgeContent"
:readonly="!isEdit" maxlength="300" show-word-limit>
</el-input>
</div>
</div>
@ -173,15 +126,8 @@
<el-dialog title="自评总结" :visible.sync="dialogVisible" width="30%">
<div>
<el-input
type="textarea"
:autosize="{ minRows: 4 }"
placeholder="0/200"
v-model="remark"
:readonly="!isEdit"
maxlength="200"
show-word-limit
>
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="0/200" v-model="remark" :readonly="!isEdit"
maxlength="200" show-word-limit>
</el-input>
</div>
@ -189,9 +135,7 @@
<el-button @click="cancelEdit">{{
isEdit ? "取 消" : "关闭"
}}</el-button>
<el-button type="primary" @click="saveEdit" v-if="isEdit"
> </el-button
>
<el-button type="primary" @click="saveEdit" v-if="isEdit"> </el-button>
</span>
</el-dialog>
</div>
@ -312,7 +256,10 @@ export default {
score: ele.score,
configId: ele.id,
remark: ele.remark,
reviewCategory: ele.reviewCategory,
}));
this.saveData.examineRemarkList = this.tableData.filter((ele)=>ele[0].reviewCategory!='发展与协作').map((ele) => ({ reviewCategory: ele[0].reviewCategory, remark: ele[0].remarkCate }))
this.saveData.taskId = this.examineTaskId;
this.saveData.examineId = this.examineId;
},
@ -326,21 +273,21 @@ export default {
return;
}
//
if (this.saveData.examineDetailList.filter((ele) => !ele.score).length) {
if (this.saveData.examineDetailList.filter((ele) => !ele.score && ele.reviewCategory != '发展与协作' || (!ele.score && !this.isNormal)).length) {
this.$alert("存在未评分绩效项,请完善后再试", "提交失败", {
confirmButtonText: "确定",
type: "warning",
});
} else if (
this.saveData.examineDetailList.filter((ele) => !ele.remark).length &&
this.saveData.examineDetailList.filter((ele) => !ele.remark && ele.reviewCategory == '发展与协作').length &&
this.isNormal &&
status
) {
this.$alert("自评总结为必填,请完善后再试", "提交失败", {
this.$alert("发展与协作下的自评总结为必填,请完善后再试", "提交失败", {
confirmButtonText: "确定",
type: "warning",
});
} else if (this.saveData.judgeContent.length > 300 && !this.isNormal) {
} else if (this.saveData.judgeContent.length > 300 && !this.isNormal && this.examineTask.templateType == '0') {
this.$message({
message: "总体评价限制300个字符",
type: "warning",
@ -350,6 +297,11 @@ export default {
message: "总体评价为必填",
type: "warning",
});
} else if (this.saveData.examineRemarkList.filter((ele) => !ele.remark).length && this.isNormal) {
this.$message({
message: "存在未填写大类评价,请完善后再试",
type: "warning",
});
} else {
if (status) {
this.$confirm(
@ -400,9 +352,11 @@ export default {
.conetentBox {
padding: 40px 30px 30px;
background-color: #fff;
height: 90vh; /* 设置整体高度 */
height: 90vh;
/* 设置整体高度 */
overflow: auto;
}
.el-table {
margin-top: 20px;
}
@ -412,31 +366,37 @@ export default {
font-size: 16px;
font-weight: bold;
}
::v-deep .el-slider__runway {
height: 14px;
border-radius: 10px;
margin: 10px !important;
/* width: 95%; */
}
::v-deep .el-slider__runway.disabled .el-slider__bar {
height: 14px;
border-radius: 10px;
background-color: #ff5722;
}
::v-deep .el-slider__stop {
height: 14px;
border-radius: 0;
z-index: 1000;
}
::v-deep .el-slider__bar {
height: 14px;
border-radius: 10px;
background: linear-gradient(to right, #ffb144, #ff7d00);
}
::v-deep .el-slider__button {
display: none;
}
.scoreText {
color: #fff;
position: absolute;
@ -445,6 +405,7 @@ export default {
display: flex;
flex-direction: row;
}
::v-deep .el-table th {
text-align: left;
font-size: 14px;
@ -456,6 +417,7 @@ export default {
font-size: 14px;
font-weight: bold;
}
.statusText {
color: #ff7d00;
position: absolute;
@ -464,43 +426,52 @@ export default {
font-size: 14px;
font-weight: 600;
}
.hasEdit {
color: #999999;
}
::v-deep .el-dialog {
margin-top: 15% !important;
}
.tableBox {
height: 75%;
overflow: auto;
padding: 20px;
background-color: #fff;
}
.tableBox ::v-deep .el-table {
border-left: 1px solid #eeeeee;
border-right: 1px solid #eeeeee;
}
.tableRow {
padding: 20px;
box-shadow: 0 0 20px #0000000f;
}
.titleBox {
font-size: 20px;
font-weight: bold;
margin-bottom: 40px;
}
.headerBox {
padding: 20px;
background-color: #f9f9f9;
border-radius: 2px;
font-size: 16px;
}
.block {
width: 4px;
height: 24px;
background-color: #4096ff;
margin-right: 10px;
}
.stepBox {
position: absolute;
top: 33px;
@ -509,6 +480,7 @@ export default {
background-color: #fff;
z-index: 100;
}
.totalBox {
width: 180px;
display: flex;
@ -516,27 +488,34 @@ export default {
font-size: 16px;
color: #333333;
}
.scoreTotal {
font-size: 28px;
font-weight: 700;
color: #ff7d00;
}
::v-deep .el-table__body .sorceTableCell .cell {
margin-bottom: 20px;
}
::v-deep .sorceTableCell.el-table__cell {
padding-right: 10px !important;
}
::v-deep .el-table__body .el-table__cell {
padding: 20px 40px;
}
::v-deep .el-table__header .el-table__cell {
padding: 14px 30px;
}
::v-deep .el-table__header .el-table__cell .cell {
padding-left: 20px !important;
}
::v-deep .editCell {
padding-right: 20px !important;

View File

@ -0,0 +1,493 @@
<template>
<div class="appraisal-manager ">
<div class="flex-row aic" style="gap: 20px;margin-bottom: 20px;">
<div>看板名称</div>
<div>
<el-input v-model="moduleName" class="filter-input" readonly>
</el-input>
</div>
<div>看板类型</div>
<el-select v-model="moduleType" placeholder="看板类型" clearable style="width: 200px" readonly>
<el-option label="年度考核" value="0" />
<el-option label="季度考核" value="1" />
<el-option label="年月考核" value="2" />
</el-select>
</div>
<div class="modal">
<div class="left">
<div class="setText" style="font-weight: 600">累计权重</div>
<el-collapse v-model="letfValue" :accordion="true" style="height: 300px; overflow: auto"
@change="showAllScoure">
<el-collapse-item v-for="(item, index) in scoreList" :key="index" :name="item.title">
<template #title>
<div class="jcsb flex-row contentTitle">
<span class="setTitle">{{ item.title }}</span>
<span class="statusText">{{ item.weight }}%</span>
</div>
</template>
<div>
<div v-for="(ele, index) in item.list" :key="index" class="flex-row jcsb leftSub" :class="{
selectClass: selectLeftRow == ele.title + ele.type,
}" @click="selectLeft(ele)">
<div>{{ ele.title }}</div>
<div class="statusText">{{ ele.weight }}%</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
<div class="flex-row jcsb" style="margin-top: 20px; padding-right: 15px">
<div class="setTitle" style="font-weight: 600">总计</div>
<div class="statusText">
{{
scoreList.reduce((total, ele) => total + (ele.weight || 0), 0)
}}%
</div>
</div>
</div>
<div class="right">
<div v-show="leftType !== '组长评估绩效指标' && leftType !== '个人自评绩效指标'">
<div class="flex-row jcsb setHeader">
<div style="width: 15%; font-weight: 600">考核项</div>
<div style="width: 50%; font-weight: 600;text-align: center;">评分标准</div>
<div class="center" style="width: 25%; font-weight: 600">
权重占比
</div>
</div>
<div v-for="(item, index) in (
(
(scoreList.find((ele) => ele.title == letfValue) || {})
.list || []
).find((ele) => ele.title + ele.type == selectLeftRow) || {}
).rightArr || []" :key="index" class="flex-row jcsb aic contentRow">
<div style="width: 15%; font-weight: 500">
{{ item.reviewItem }}
</div>
<div class="center" style="width: 50%;padding: 0 20px;">
{{ item.remarks }}
</div>
<div class="center" style="width: 25%">
<div class="flex-row jcsb" style="
margin-left: 10px;
width: 100%;
color: #999;
font-weight: 500;
font-size: 14px;
font-weight: 600;
">
<div>0</div>
<div v-show="item.weight != 20">20</div>
</div>
<div class="scoreText aic" v-show="item.weight != 0" :style="{
left: item.weight * 4.5 - 2.5 + '%',
}">
<img src="@/assets/task/score.png" :style="{
height: '28px',
width: '34px',
zIndex: 0,
position: 'absolute',
top: '-2px',
}" alt="" />
<div :style="{
zIndex: 10,
textIndent: item.weight < 10 ? '13px' : '10px',
fontSize: '12px',
}">
{{ item.weight }}
</div>
</div>
<!-- <div class="flex-row jcsb scoreBox" style="margin-left: 15px">
<div>0%</div>
<div class="scoreText">{{ item.weight }}%</div>
<div>20%</div>
</div> -->
<div v-for="item in item.weight == 0 ? 0 : item.weight - 1" :key="item" class="stepBox"
:style="{
left: item * 5 + 4 + '%',
}"></div>
<el-slider :disabled="isDisabled" v-model="item.weight" :max="20"
@change="changeTotal"></el-slider>
</div>
</div>
</div>
<div v-show="leftType == '组长评估绩效指标' || leftType == '个人自评绩效指标'">
<div v-for="(ele, index) in
(scoreList.find((ele) => ele.title == leftType) || {})
.list || []
" :key="index">
<div style="margin: 10px;font-weight: 600;font-size: 18px;">{{ ele.title }}</div>
<div class="flex-row jcsb setHeader">
<div style="width: 15%; font-weight: 600">考核项</div>
<div style="width: 50%; font-weight: 600;text-align: center;">评分标准</div>
<div class="center" style="width: 25%; font-weight: 600">
权重占比
</div>
</div>
<div style="margin-bottom: 50px;">
<div v-for="(item, index) in (ele.rightArr || [])" class="flex-row jcsb aic contentRow">
<div style="width: 15%; font-weight: 600">
{{ item.reviewItem }}
</div>
<div class="center" style="width: 50%;padding: 0 20px;">
{{ item.remarks }}
</div>
<div class="center" style="width: 25%">
<div class="flex-row jcsb" style="
margin-left: 10px;
width: 100%;
color: #999;
font-weight: 500;
font-size: 14px;
font-weight: 600;
">
<div>0</div>
<div v-show="item.weight != 20">20</div>
</div>
<div class="scoreText aic" v-show="item.weight != 0" :style="{
left: item.weight * 4.5 - 2.5 + '%',
}">
<img src="@/assets/task/score.png" :style="{
height: '28px',
width: '34px',
zIndex: 0,
position: 'absolute',
top: '-2px',
}" alt="" />
<div :style="{
zIndex: 10,
textIndent: item.weight < 10 ? '13px' : '10px',
fontSize: '12px',
}">
{{ item.weight }}
</div>
</div>
<div v-for="item in item.weight == 0 ? 0 : item.weight - 1" :key="item"
class="stepBox" :style="{
left: item * 5 + 4 + '%',
}"></div>
<el-slider :disabled="isDisabled" v-model="item.weight" :max="20"
@change="changeTotal"></el-slider>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { taskApi } from "@/utils/api";
export default {
components: {
},
data() {
return {
moduleId: '',
moduleName: '',
moduleType: '',
scoreList: [],
letfValue: "",
selectLeftRow: '',
leftType: '',
isDisabled: true
};
},
methods: {
getDetail() {
taskApi.getTaskModelSet(this.moduleId).then((res) => {
let objData = {};
res.data.forEach((ele) => {
if (!objData[ele.reviewType]) objData[ele.reviewType] = [];
objData[ele.reviewType].push(ele);
});
let arrList = {};
Object.keys(objData).forEach((ele) => {
let arr = [];
objData[ele].forEach((item) => {
if (!arr[item.reviewCategory]) arr[item.reviewCategory] = [];
arr[item.reviewCategory].push(item);
});
arrList[ele] = arr;
});
this.scoreList = [
{
title: "组长评估绩效指标",
list: Object.keys(arrList["0"]).map((ele) => ({
title: ele,
weight: arrList["0"][ele].reduce(
(total, item) => (item.weight || 0) + total,
0
),
rightArr: arrList["0"][ele],
type: 0,
})),
weight: Object.values(arrList["0"]).reduce(
(total, item) =>
(item.reduce((total, item) => (item.weight || 0) + total, 0) ||
0) + total,
0
),
},
{
title: "个人自评绩效指标",
list: Object.keys(arrList["1"]).map((ele) => ({
title: ele,
weight: arrList["1"][ele].reduce(
(total, item) => (item.weight || 0) + total,
0
),
rightArr: arrList["1"][ele],
type: 1,
})),
weight: Object.values(arrList["1"]).reduce(
(total, item) =>
(item.reduce((total, item) => (item.weight || 0) + total, 0) ||
0) + total,
0
),
},
{
title: "系统核算绩效指标",
list: Object.keys(arrList["2"] || {}).map((ele) => ({
title: ele,
weight: arrList["2"][ele].reduce(
(total, item) => (item.weight || 0) + total,
0
),
rightArr: arrList["2"][ele],
type: 2,
})),
weight: Object.values(arrList["2"] || {}).reduce(
(total, item) =>
(item.reduce((total, item) => (item.weight || 0) + total, 0) ||
0) + total,
0
),
},
];
if (!arrList["2"]) {
this.scoreList.length = 2
}
this.dialogVisible2 = true;
});
},
selectLeft(row) {
this.leftType = ''
this.selectLeftRow = row.title + row.type;
},
changeTotal(data) {
this.$nextTick(() => {
this.scoreList.forEach((ele) => {
ele.list.forEach((item) => {
item.weight = item.rightArr.reduce(
(total, ele) => total + (ele.weight || 0),
0
);
});
ele.weight = ele.list.reduce(
(total, ele) => total + (ele.weight || 0),
0
);
});
});
},
showAllScoure(val) {
if (val)
this.leftType = val
else {
this.leftType = parseInt(this.selectLeftRow)==0?'组长评估绩效指标':'个人自评绩效指标'
}
}
},
mounted() {
this.moduleId = this.$route.query.id
this.moduleName = this.$route.query.moduleName
this.moduleType = this.$route.query.moduleType
this.getDetail()
},
};
</script>
<style lang="scss" scoped>
.appraisal-manager {
padding: 30px;
background-color: #fff;
height: calc(100vh - 100px);
/* 设置整体高度 */
}
.modal {
display: flex;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
height: 100%;
}
.left {
width: 20%;
padding: 20px;
border-right: 1px solid #ccc;
height: 100%;
overflow: auto;
}
.right {
width: 80%;
padding: 20px 40px;
height: 100%;
overflow: auto;
div.center {
text-align: center;
position: relative;
}
}
.scoreBox {
position: absolute;
top: 45px;
right: -20px;
}
::v-deep .el-slider__runway {
height: 14px;
border-radius: 10px;
margin: 10px !important;
/* width: 95%; */
}
::v-deep .el-slider__runway.disabled .el-slider__bar {
height: 14px;
border-radius: 10px;
background-color: #ff5722;
}
::v-deep .el-slider__stop {
height: 14px;
border-radius: 0;
z-index: 1000;
}
::v-deep .el-slider__bar {
height: 14px;
border-radius: 10px;
background: linear-gradient(to right, #ffb144, #ff7d00);
}
::v-deep .el-slider__button {
display: none;
}
.scoreText {
color: #1686d8;
}
.setText {
margin-bottom: 20px;
text-align: right;
}
.leftSub {
padding: 10px 20px 10px 10px;
margin-bottom: 5px;
cursor: pointer;
}
.setTitle {
font-weight: bold;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
::v-deep .el-collapse-item__header {}
.contentTitle {}
.statusText {
color: #ff5722;
}
::v-deep .el-collapse {
border: none !important;
}
.search-buttons ::v-deep .el-button {
width: 90px !important;
height: 36px;
}
::v-deep .operation-buttons .el-button {
padding: 4px 8px;
margin: 0 2px;
font-weight: 600;
font-size: 14px;
}
.selectClass {
background-color: #4096ff;
color: #fff;
}
.scoreText {
color: #fff;
position: absolute;
top: 2px;
font-weight: 500;
display: flex;
flex-direction: row;
width: 40px;
}
.block {
width: 4px;
height: 24px;
background-color: #4096ff;
margin-right: 10px;
}
.stepBox {
position: absolute;
top: 29px;
height: 14px;
width: 2px;
background-color: #fff;
z-index: 100;
}
.totalBox {
width: 150px;
display: flex;
flex-direction: row;
font-size: 14px;
color: #333333;
}
.contentRow {
border-bottom: 1px solid #ccc;
padding: 15px 0;
}
.setHeader {
background-color: #f8f8f9;
padding: 15px;
}
</style>

View File

@ -0,0 +1,492 @@
<template>
<div class="project-list">
<div class="search-bar">
<el-form :inline="true" :model="searchForm" class="demo-form-inline" size="small">
<el-form-item label="看板名称" class="form-item">
<el-input v-model="searchForm.templateName" placeholder="看板名称" style="width: 300px"></el-input>
</el-form-item>
<el-form-item label="创建人" class="form-item">
<el-input v-model="searchForm.createByName" placeholder="创建人" readonly
@click.native="openUserSelectDialog"><el-button slot="append"
icon="el-icon-s-custom"></el-button></el-input>
</el-form-item>
<el-form-item label="考核类型" class="form-item">
<el-select v-model="searchForm.templateType" placeholder="状态" clearable style="width: 300px">
<el-option label="年度考核" value="0" />
<el-option label="季度考核" value="1" />
<el-option label="年月考核" value="2" />
</el-select>
</el-form-item>
<el-form-item class="search-buttons">
<el-button type="primary" @click="onSearch"></el-button>
<el-button @click="onReset"></el-button>
</el-form-item>
</el-form>
</div>
<!-- <div class="table-actions mb10">
<el-button type="primary" size="mini" @click="addTask" style="height: 36px">+ 新增看板</el-button>
</div> -->
<div class="f1 df">
<CustomTable :columns="columns" :tableData="tableData" :total="total" :show-selection="false"
:show-index="true" @size-change="handleSizeChange" @current-change="handleCurrentChange"
tableHeight="495px">
<template slot="operation" slot-scope="{ row }">
<div class="operation-buttons">
<el-button type="text" size="mini" @click="viewDetail(row)"></el-button>
<!-- <el-button @click="viewDetail(row)" type="text" size="mini">编辑</el-button> -->
<el-button type="text" size="mini" @click="delTask(row)"></el-button>
</div>
</template>
</CustomTable>
</div>
<SelectUser :dialogVisible="userSelectDialogVisible" :currentSelectedUser="currentSelectedUser"
:currentSelectedUserName="currentSelectedUserName" :highligt="true" ref="selectUserRef"
@confirm="handleUserConfirm" @close="handleUserClose" />
</div>
</template>
<script>
import CustomTable from "@/components/CustomTable.vue";
import SelectUser from "@/components/SelectUser.vue";
import { taskApi } from "@/utils/api";
export default {
components: {
CustomTable,
SelectUser,
},
data() {
return {
searchForm: {
templateName: "",
templateType: "",
createBy: "",
createByName: ''
},
columns: [
{ prop: "templateName", label: "看板名称" },
{
prop: "templateType", label: "考核类型", type: "status",
callback: (value) => {
if (value == 0) var type = "年度考核";
else if (value == 1) var type = "季度考核";
else if (value == 2) var type = "月度考核";
return type
},
},
{
prop: "createByName",
label: "创建人",
},
{
prop: "createTime",
label: "创建日期",
},
{
prop: "operation",
label: "操作",
width: "250",
className: "operation-column",
},
],
tableData: [],
total: 0,
userSelectDialogVisible: false,
currentSelectedUser: [],
currentSelectedUserName: [],
pageNum: 1, //
pageSize: 10, //
statusList: [
{ label: "全部", value: "" },
{ label: "进行中", value: "0" },
{ label: "已过期", value: "2" },
],
dialogVisible1: false,
isEdit: false,
taskData: {
id: "",
taskName: "",
peopleNumberDetail: "",
userIdList: [],
endTime: "",
peopleNumber: 0,
year: "",
},
rules: {
taskName: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ min: 1, max: 20, message: "长度限制20个字符", trigger: "blur" },
],
peopleNumberDetail: [
{ required: true, message: "请选择考核人员", trigger: "change" },
],
endTime: [
{ required: true, message: "请选择截止时间", trigger: "blur" },
],
year: [{ required: true, message: "请选择年份", trigger: "blur" }],
},
dialogVisible2: false,
letfValue: "",
scoreList: [],
modelList: [],
};
},
watch: {
dialogVisible1(newVal) {
if (newVal) {
this.$nextTick(() => {
this.$refs.selectUserRef?.$refs.customTableRef?.handleCurrentChange(
1
);
});
}
},
},
methods: {
onSearch() {
this.getTaskModelList();
},
onReset() {
Object.keys(this.searchForm).forEach((key) => {
this.searchForm[key] = "";
});
this.getTaskModelList();
},
getTaskModelList() {
taskApi
.getTaskModel({
...this.searchForm,
pageNum: this.pageNum,
pageSize: this.pageSize,
})
.then((res) => {
this.tableData = res.rows;
this.total = res.total;
});
},
handleSizeChange(size) {
this.pageSize = size;
this.pageNum = 1; //
this.getTaskModelList();
},
handleCurrentChange(page) {
this.pageNum = page;
this.getTaskModelList();
},
openUserSelectDialog() {
this.userSelectDialogVisible = true;
this.$nextTick(() => {
this.$refs.selectUserRef?.$refs.customTableRef?.clearSelection();
this.currentSelectedUser = [this.searchForm.createBy];
this.currentSelectedUserName = [this.searchForm.createName];
});
},
handleUserConfirm(data) {
this.searchForm.createByName = data[0].nickName;
this.searchForm.createBy = data[0].userId;
},
handleUserClose() {
this.userSelectDialogVisible = false;
},
addTask() {
this.isEdit = false;
this.dialogVisible1 = true;
this.taskData = {
id: "",
taskName: "",
peopleNumberDetail: "",
userIdList: [],
endTime: "",
peopleNumber: 0,
};
},
viewDetail(row) {
this.$router.push({
path: `/workAppraisal/moduleDetail?id=${row.id}&moduleName=${row.templateName}&moduleType=${row.templateType}`
})
},
delTask(row) {
this.$confirm(
"是否确认删除该条看板",
"确认删除",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
).then(() => {
taskApi.delTaskModule(row.id).then((res) => {
this.$message({
type: "success",
message: "删除成功!",
});
this.getTaskModelList();
});
});
},
},
mounted() {
this.getTaskModelList();
},
};
</script>
<style lang="scss" scoped>
.project-list {
padding: 20px;
background-color: white;
height: 88vh;
box-sizing: border-box;
overflow: hidden;
display: flex;
flex-direction: column;
}
.search-bar {
margin-bottom: 20px;
}
.demo-form-inline {
// display: flex;
// flex-wrap: nowrap;
// align-items: flex-start;
}
.demo-form-inline .el-form-item {
// margin-right: 50px; /* 30px */
// margin-bottom: 0;
}
.demo-form-inline .el-form-item:last-child {
margin-right: 0;
/* 移除最后一个元素的右边距 */
}
.form-item {
flex: 1;
}
.form-item ::v-deep .el-form-item__content {
// width: 100%;
}
.form-item ::v-deep .el-input,
.form-item ::v-deep .el-select {
// width: 100%;
}
.search-buttons {
white-space: nowrap;
}
::v-deep .operation-buttons .el-button {
padding: 4px 8px;
margin: 0 2px;
}
::v-deep .operation-column {
background-color: #ffffff;
box-shadow: -2px 0 5px rgba(241, 112, 6, 0.1);
}
.el-button.is-text {
min-width: 32px !important;
}
.dialog-footer {
display: flex;
justify-content: center;
align-items: center;
}
.dialog-footer .el-button {
margin: 0 10px;
}
.delete-content {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.warning-icon {
font-size: 24px;
color: #e6a23c;
margin-right: 10px;
}
/* 添加以下样式来使对话框垂直居中 */
::v-deep .delete-dialog.el-dialog {
margin-top: 0 !important;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
::v-deep .el-table th {
text-align: center;
}
::v-deep .el-table .cell {
text-align: center;
}
::v-deep .el-dialog {
margin-top: 10% !important;
}
.modal {
display: flex;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
}
.left {
width: 40%;
padding: 20px;
border-right: 1px solid #ccc;
height: 450px;
overflow: auto;
}
.right {
width: 60%;
padding: 20px 40px;
height: 450px;
overflow: auto;
div.center {
text-align: center;
position: relative;
}
}
.scoreBox {
position: absolute;
top: 45px;
right: -20px;
}
::v-deep .el-slider__runway {
height: 14px;
border-radius: 10px;
margin: 10px !important;
/* width: 95%; */
}
::v-deep .el-slider__runway.disabled .el-slider__bar {
height: 14px;
border-radius: 10px;
background-color: #ff5722;
}
::v-deep .el-slider__stop {
height: 14px;
border-radius: 0;
z-index: 1000;
}
::v-deep .el-slider__bar {
height: 14px;
border-radius: 10px;
background: linear-gradient(to right, #ffb144, #ff7d00);
}
::v-deep .el-slider__button {
display: none;
}
.scoreText {
color: #1686d8;
}
.setText {
margin-bottom: 20px;
text-align: right;
}
.leftSub {
padding: 10px 20px 10px 10px;
margin-bottom: 5px;
cursor: pointer;
}
.setTitle {
font-weight: bold;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
::v-deep .el-collapse-item__header {}
.contentTitle {}
.statusText {
color: #ff5722;
}
::v-deep .el-collapse {
border: none !important;
}
.search-buttons ::v-deep .el-button {
width: 90px !important;
height: 36px;
}
::v-deep .operation-buttons .el-button {
padding: 4px 8px;
margin: 0 2px;
font-weight: 600;
font-size: 14px;
}
.selectClass {
background-color: #4096ff;
color: #fff;
}
.scoreText {
color: #fff;
position: absolute;
top: 2px;
font-weight: 500;
display: flex;
flex-direction: row;
width: 40px;
}
.block {
width: 4px;
height: 24px;
background-color: #4096ff;
margin-right: 10px;
}
.stepBox {
position: absolute;
top: 29px;
height: 14px;
width: 2px;
background-color: #fff;
z-index: 100;
}
.totalBox {
width: 150px;
display: flex;
flex-direction: row;
font-size: 14px;
color: #333333;
}
</style>

View File

@ -1,44 +1,18 @@
<template>
<div class="project-list">
<div class="search-bar">
<el-form
:inline="true"
:model="searchForm"
class="demo-form-inline"
size="small"
>
<el-form :inline="true" :model="searchForm" class="demo-form-inline" size="small">
<el-form-item label="任务名称" class="form-item">
<el-input
v-model="searchForm.taskName"
placeholder="任务名称"
style="width: 300px;"
></el-input>
<el-input v-model="searchForm.taskName" placeholder="任务名称" style="width: 300px"></el-input>
</el-form-item>
<el-form-item label="任务状态" class="form-item">
<el-select
v-model="searchForm.taskStatus"
placeholder="状态"
clearable
style="width: 300px;"
>
<el-option
v-for="item in statusList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="searchForm.taskStatus" placeholder="状态" clearable style="width: 300px">
<el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="任务年份" class="form-item">
<el-date-picker
v-model="searchForm.year"
type="year"
style="width: 300px"
placeholder="选择年份"
value-format="yyyy"
>
<el-date-picker v-model="searchForm.year" type="year" style="width: 300px" placeholder="选择年份"
value-format="yyyy">
</el-date-picker>
</el-form-item>
<el-form-item class="search-buttons">
@ -48,115 +22,65 @@
</el-form>
</div>
<div class="table-actions mb10">
<el-button
type="primary"
size="mini"
@click="addTask"
style="height: 36px"
>+ 新增任务</el-button
>
<el-button type="primary" size="mini" @click="addTask" style="height: 36px">+ 新增任务</el-button>
</div>
<div class="f1 df">
<CustomTable
:columns="columns"
:tableData="tableData"
:total="total"
:show-selection="false"
:show-index="true"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
tableHeight="495px"
>
<CustomTable :columns="columns" :tableData="tableData" :total="total" :show-selection="false" :show-index="true"
@size-change="handleSizeChange" @current-change="handleCurrentChange" tableHeight="495px">
<template slot="operation" slot-scope="{ row }">
<div class="operation-buttons">
<el-button @click="editTask(row)" type="text" size="mini"
>编辑</el-button
>
<el-button
v-if="row.taskStatus == 0"
type="text"
size="mini"
@click="setTask(row)"
>指标配置</el-button
>
<el-button type="text" size="mini" @click="delTask(row)"
>删除</el-button
>
<el-button @click="editTask(row)" type="text" size="mini">编辑</el-button>
<el-button v-if="row.taskStatus == 0" type="text" size="mini" @click="setTask(row)"></el-button>
<el-button type="text" size="mini" @click="delTask(row)"></el-button>
</div>
</template>
</CustomTable>
</div>
<SelectUser
:dialogVisible="userSelectDialogVisible"
:currentSelectedUser="currentSelectedUser"
:currentSelectedUserName="currentSelectedUserName"
:showSelection="true"
:highligt="false"
:selectable="selectable"
ref="selectUserRef"
@confirm="handleUserConfirm"
@close="handleUserClose"
/>
<el-dialog
:title="isEdit ? '编辑考核任务' : '新增考核任务'"
:visible.sync="dialogVisible1"
width="25%"
>
<SelectUser :dialogVisible="userSelectDialogVisible" :currentSelectedUser="currentSelectedUser"
:currentSelectedUserName="currentSelectedUserName" :showSelection="true" :highligt="false"
:selectable="selectable" ref="selectUserRef" @confirm="handleUserConfirm" @close="handleUserClose" />
<el-dialog :title="isEdit ? '编辑考核任务' : '新增考核任务'" :visible.sync="dialogVisible1" width="25%">
<div>
<el-form
:model="taskData"
size="small"
ref="taskFormRef"
:rules="rules"
label-width="100px"
>
<el-form :model="taskData" size="small" ref="taskFormRef" :rules="rules" label-width="100px">
<el-form-item label="任务名称" class="form-item" prop="taskName">
<el-input
v-model="taskData.taskName"
placeholder="0/20"
style="width: 90%"
></el-input>
<el-input v-model="taskData.taskName" placeholder="0/20" style="width: 90%"></el-input>
</el-form-item>
<el-form-item
label="考核人员"
class="form-item"
prop="peopleNumberDetail"
>
<el-input
v-model="taskData.peopleNumberDetail"
placeholder="考核人员"
readonly
style="width: 90%"
@click.native="openUserSelectDialog"
><el-button slot="append" icon="el-icon-s-custom"></el-button
></el-input>
<el-form-item label="考核人员" class="form-item" prop="peopleNumberDetail">
<el-input v-model="taskData.peopleNumberDetail" placeholder="考核人员" readonly style="width: 90%"
@click.native="openUserSelectDialog"><el-button slot="append"
icon="el-icon-s-custom"></el-button></el-input>
</el-form-item>
<el-form-item label="截止时间" class="form-item" prop="endTime">
<el-date-picker
v-model="taskData.endTime"
type="date"
style="width: 90%"
placeholder="选择日期"
value-format="yyyy-MM-dd 23:59:59"
:picker-options="{
<el-date-picker v-model="taskData.endTime" type="date" style="width: 90%" placeholder="选择日期"
value-format="yyyy-MM-dd 23:59:59" :picker-options="{
disabledDate: disabledDate,
}"
>
}">
</el-date-picker>
</el-form-item>
<el-form-item label="年份" class="form-item" prop="year">
<el-date-picker
v-model="taskData.year"
type="year"
style="width: 90%"
placeholder="选择年份"
value-format="yyyy"
:picker-options="{
<el-date-picker v-model="taskData.year" type="year" style="width: 90%" placeholder="选择年份"
value-format="yyyy" :picker-options="{
disabledDate: disabledDate,
}"
>
}">
</el-date-picker>
</el-form-item>
<el-form-item label="考核模板" class="form-item" prop="templateId">
<div>
<el-radio-group v-model="taskData.templateType" @change="() => {
taskData.templateId = ''
}" :disabled="taskData.taskStatus == 2">
<el-radio label="0">年度看板</el-radio>
<el-radio label="1">季度看板</el-radio>
<el-radio label="2">月度看板</el-radio>
</el-radio-group>
<el-select v-model="taskData.templateId" placeholder="选择看板" clearable style="width: 300px"
:disabled="taskData.taskStatus == 2">
<el-option v-for="item in modelList.filter((ele) => ele.templateType == taskData.templateType)"
:key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
@ -168,16 +92,8 @@
<div class="modal">
<div class="left">
<div class="setText" style="font-weight: 600">累计权重</div>
<el-collapse
v-model="letfValue"
:accordion="true"
style="height: 300px; overflow: auto"
>
<el-collapse-item
v-for="(item, index) in scoreList"
:key="index"
:name="item.title"
>
<el-collapse v-model="letfValue" :accordion="true" style="height: 300px; overflow: auto">
<el-collapse-item v-for="(item, index) in scoreList" :key="index" :name="item.title">
<template #title>
<div class="jcsb flex-row contentTitle">
<span class="setTitle">{{ item.title }}</span>
@ -185,25 +101,16 @@
</div>
</template>
<div>
<div
v-for="(ele, index) in item.list"
:key="index"
class="flex-row jcsb leftSub"
:class="{
<div v-for="(ele, index) in item.list" :key="index" class="flex-row jcsb leftSub" :class="{
selectClass: selectLeftRow == ele.title + ele.type,
}"
@click="selectLeft(ele)"
>
}" @click="selectLeft(ele)">
<div>{{ ele.title }}</div>
<div class="statusText">{{ ele.weight }}%</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
<div
class="flex-row jcsb"
style="margin-top: 20px; padding-right: 15px"
>
<div class="flex-row jcsb" style="margin-top: 20px; padding-right: 15px">
<div class="setTitle" style="font-weight: 600">总计</div>
<div class="statusText">
{{
@ -215,63 +122,47 @@
<div class="right">
<div class="flex-row jcsb" style="margin-bottom: 10px">
<div style="width: 50%; font-weight: 600">指标</div>
<div class="center" style="width: 50%;font-weight: 600">权重占比</div>
<div class="center" style="width: 50%; font-weight: 600">
权重占比
</div>
</div>
<div>
<div
v-for="(item, index) in (
<div v-for="(item, index) in (
(
(scoreList.find((ele) => ele.title == letfValue) || {})
.list || []
).find((ele) => ele.title + ele.type == selectLeftRow) || {}
).rightArr || []"
:key="index"
style="margin-bottom: 10px"
class="flex-row jcsb aic"
>
).rightArr || []" :key="index" style="margin-bottom: 10px" class="flex-row jcsb aic">
<div style="width: 50%; font-weight: 600">
{{ item.reviewItem }}
</div>
<div class="center" style="width: 50%">
<div
class="flex-row jcsb"
style="
<div class="flex-row jcsb" style="
margin-left: 10px;
width: 100%;
color: #999;
font-weight: 500;
font-size: 14px;
font-weight: 600;
"
>
">
<div>0</div>
<div v-show="item.weight != 20">20</div>
</div>
<div
class="scoreText aic"
v-show="item.weight != 0"
:style="{
<div class="scoreText aic" v-show="item.weight != 0" :style="{
left: item.weight * 4.5 - 2.5 + '%',
}"
>
<img
src="@/assets/task/score.png"
:style="{
}">
<img src="@/assets/task/score.png" :style="{
height: '28px',
width: '34px',
zIndex: 0,
position: 'absolute',
top: '-2px',
}"
alt=""
/>
<div
:style="{
}" alt="" />
<div :style="{
zIndex: 10,
textIndent: item.weight < 10 ? '13px' : '10px',
fontSize: '12px',
}"
>
}">
{{ item.weight }}
</div>
</div>
@ -280,19 +171,10 @@
<div class="scoreText">{{ item.weight }}%</div>
<div>20%</div>
</div> -->
<div
v-for="item in item.weight == 0 ? 0 : item.weight - 1"
:key="item"
class="stepBox"
:style="{
<div v-for="item in item.weight == 0 ? 0 : item.weight - 1" :key="item" class="stepBox" :style="{
left: item * 5 + 4 + '%',
}"
></div>
<el-slider
v-model="item.weight"
:max="20"
@change="changeTotal"
></el-slider>
}"></div>
<el-slider v-model="item.weight" :max="20" @change="changeTotal"></el-slider>
</div>
</div>
</div>
@ -335,8 +217,7 @@ export default {
if (value == 2) var color = "#999";
else var color = "#4096FF";
return `<span style="color: ${color}">${
value ? "已过期" : "进行中"
return `<span style="color: ${color}">${value ? "已过期" : "进行中"
}</span>`;
},
},
@ -389,11 +270,14 @@ export default {
userIdList: [],
endTime: "",
peopleNumber: 0,
templateType:'0',
templateId:'',
year: "",
taskStatus: 0
},
rules: {
taskName: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ required: true, message: "请输入任务名称", trigger: "blur" },
{ min: 1, max: 20, message: "长度限制20个字符", trigger: "blur" },
],
peopleNumberDetail: [
@ -403,11 +287,13 @@ export default {
{ required: true, message: "请选择截止时间", trigger: "blur" },
],
year: [{ required: true, message: "请选择年份", trigger: "blur" }],
templateId: [{ required: true, message: "请选择任务看板", trigger: "blur" }],
},
dialogVisible2: false,
letfValue: "",
scoreList: [],
selectRow: {},
modelList: [],
};
},
watch: {
@ -495,6 +381,10 @@ export default {
userIdList: [],
endTime: "",
peopleNumber: 0,
templateType: '0',
templateId: '',
taskStatus: 0
};
this.selectRow = {};
},
@ -507,6 +397,9 @@ export default {
this.taskData.peopleNumberDetail = row.peopleNumberDetail;
this.taskData.userIdList = row.userIdList;
this.taskData.endTime = row.endTime;
this.taskData.templateId = row.templateId;
this.taskData.templateType = row.templateType;
this.taskData.taskStatus = row.taskStatus;
this.taskData.year = String(row.year);
this.selectRow = row;
},
@ -566,7 +459,7 @@ export default {
},
{
title: "系统核算绩效指标",
list: Object.keys(arrList["2"]).map((ele) => ({
list: Object.keys(arrList["2"] || {}).map((ele) => ({
title: ele,
weight: arrList["2"][ele].reduce(
(total, item) => (item.weight || 0) + total,
@ -575,7 +468,7 @@ export default {
rightArr: arrList["2"][ele],
type: 2,
})),
weight: Object.values(arrList["2"]).reduce(
weight: Object.values(arrList["2"] || {}).reduce(
(total, item) =>
(item.reduce((total, item) => (item.weight || 0) + total, 0) ||
0) + total,
@ -583,6 +476,9 @@ export default {
),
},
];
if (!arrList["2"]) {
this.scoreList.length = 2
}
this.dialogVisible2 = true;
});
@ -684,15 +580,24 @@ export default {
});
},
selectable(row, index) {
if(row.roles.find((ele)=>ele.roleName=='普通员工')){
return true
if (row.roles.find((ele) => ele.roleName == "普通员工")) {
return true;
} else {
return false
}
return false;
}
},
async getTaskModel() {
const res = await taskApi.getTaskModel({ pageNum: 1, pageSize: 1000 });
this.modelList = res.rows.map((ele) => ({
value: ele.id,
label: ele.templateName,
templateType: ele.templateType
}));
},
},
mounted() {
this.getTaskList();
this.getTaskModel();
},
};
</script>
@ -724,7 +629,8 @@ export default {
}
.demo-form-inline .el-form-item:last-child {
margin-right: 0; /* 移除最后一个元素的右边距 */
margin-right: 0;
/* 移除最后一个元素的右边距 */
}
.form-item {
@ -789,6 +695,7 @@ export default {
left: 50%;
transform: translate(-50%, -50%);
}
::v-deep .el-table th {
text-align: center;
}
@ -796,14 +703,17 @@ export default {
::v-deep .el-table .cell {
text-align: center;
}
::v-deep .el-dialog {
margin-top: 10% !important;
}
.modal {
display: flex;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
}
.left {
width: 40%;
padding: 20px;
@ -811,89 +721,108 @@ export default {
height: 450px;
overflow: auto;
}
.right {
width: 60%;
padding: 20px 40px;
height: 450px;
overflow: auto;
div.center {
text-align: center;
position: relative;
}
}
.scoreBox {
position: absolute;
top: 45px;
right: -20px;
}
::v-deep .el-slider__runway {
height: 14px;
border-radius: 10px;
margin: 10px !important;
/* width: 95%; */
}
::v-deep .el-slider__runway.disabled .el-slider__bar {
height: 14px;
border-radius: 10px;
background-color: #ff5722;
}
::v-deep .el-slider__stop {
height: 14px;
border-radius: 0;
z-index: 1000;
}
::v-deep .el-slider__bar {
height: 14px;
border-radius: 10px;
background: linear-gradient(to right, #ffb144, #ff7d00);
}
::v-deep .el-slider__button {
display: none;
}
.scoreText {
color: #1686d8;
}
.setText {
margin-bottom: 20px;
text-align: right;
}
.leftSub {
padding: 10px 20px 10px 10px;
margin-bottom: 5px;
cursor: pointer;
}
.setTitle {
font-weight: bold;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
::v-deep .el-collapse-item__header {
}
.contentTitle {
}
::v-deep .el-collapse-item__header {}
.contentTitle {}
.statusText {
color: #ff5722;
}
::v-deep .el-collapse {
border: none !important;
}
.search-buttons ::v-deep .el-button {
width: 90px !important;
height: 36px;
}
::v-deep .operation-buttons .el-button {
padding: 4px 8px;
margin: 0 2px;
font-weight: 600;
font-size: 14px;
}
.selectClass {
background-color: #4096ff;
color: #fff;
}
.scoreText {
color: #fff;
position: absolute;
@ -903,12 +832,14 @@ export default {
flex-direction: row;
width: 40px;
}
.block {
width: 4px;
height: 24px;
background-color: #4096ff;
margin-right: 10px;
}
.stepBox {
position: absolute;
top: 29px;
@ -917,6 +848,7 @@ export default {
background-color: #fff;
z-index: 100;
}
.totalBox {
width: 150px;
display: flex;

View File

@ -162,11 +162,11 @@
</el-table-column>
<el-table-column label="操作" width="200">
<template #default="scope">
<div v-show="!disableTable">
<div>
<el-button type="text" @click="handleFile(scope.row)">
附件详情
</el-button>
<el-button type="text" @click="handleEdit(scope.row)">
<el-button type="text" @click="handleEdit(scope.row)" v-show="!disableTable">
{{ scope.row.loggerId && !scope.row.edit ? "编辑" : "确认" }}
</el-button>
@ -174,6 +174,7 @@
type="text"
@click="handleDelete(scope.row, scope.$index)"
style="color: #666"
v-show="!disableTable"
>
{{ scope.row.loggerId && !scope.row.edit ? "删除" : "取消" }}
</el-button>
@ -188,7 +189,7 @@
:close-on-click-modal="false"
>
<div v-loading="fileLoading">
<div>
<div v-show="!disableTable">
<el-upload
class="upload-demo"
ref="upload"
@ -249,7 +250,7 @@
<el-table-column label="操作" width="120">
<template #default="scope">
<div>
<el-button type="text" @click="delFile(scope.row)">
<el-button type="text" @click="delFile(scope.row)" v-show="!disableTable">
删除
</el-button>
</div>
@ -304,6 +305,7 @@ export default {
filePng,
zipPng,
imagePng,
delFileArr:[]
};
},
methods: {
@ -328,7 +330,7 @@ export default {
ele.showContent = false;
return ele;
});
if (this.tableData.length == 0) {
if (this.tableData.length == 0&&!this.disableTable) {
this.handleAdd();
}
});
@ -406,6 +408,12 @@ export default {
await workLogApi.addLog(param);
this.$emit("changeCaleder");
}
if(this.delFileArr.length){
systemApi.delFile({ids:this.delFileArr}).then((res) => {
this.fileList = []
this.delFileArr=[]
});
}
this.$modal.msgSuccess("操作成功");
row.edit = false;
this.getLogList();
@ -445,6 +453,8 @@ export default {
fileUrl: res.url,
});
} else {
this.fileLoading = false;
this.$message({
type: "error",
message: res.msg,
@ -455,10 +465,27 @@ export default {
this.dialogVisibleFile = false;
this.fileList = [];
},
saveFile() {
async saveFile() {
this.dialogVisibleFile = false;
this.checkRow.fileList = this.fileList;
if(this.checkRow.loggerId){
await workLogApi.editLog(this.checkRow);
if(this.delFileArr.length){
systemApi.delFileBatch(this.delFileArr.join(',')).then((res) => {
this.fileList = []
this.delFileArr=[]
this.getLogList();
});
}else{
this.getLogList();
}
}
this.$message({
type: "success",
message: "保存成功!",
});
},
async getAllProject() {
const response = await projectApi.listProject({
@ -563,7 +590,7 @@ export default {
cancelButtonText: "取消",
type: "warning",
}).then(() => {
systemApi.delFile(row.id).then((res) => {
this.delFileArr.push(row.id)
this.fileList = this.fileList.filter(
(ele) => ele.fileNewName != row.fileNewName
);
@ -572,7 +599,6 @@ export default {
message: "删除成功!"
})
});
});
} else {
this.fileList = this.fileList.filter(
(ele) => ele.fileNewName != row.fileNewName