<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.taskName" placeholder="任务名称" ></el-input> </el-form-item> <el-form-item label="任务状态" class="form-item"> <el-select v-model="searchForm.taskStatus" placeholder="状态" clearable > <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" /> </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" >+ 新增任务</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 @click="editTask(row)" type="text" size="mini" icon="el-icon-edit" >编辑</el-button > <el-button type="text" size="mini" icon="el-icon-setting" @click="setTask(row)" >指标配置</el-button > <el-button type="text" size="mini" icon="el-icon-delete" @click="delTask(row)" >删除</el-button > </div> </template> </CustomTable> </div> <SelectUser :dialogVisible="userSelectDialogVisible" :currentSelectedUser="currentSelectedUser" :showSelection="true" :highligt="false" @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-item label="任务名称" class="form-item" prop="taskName"> <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> <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" > </el-date-picker> </el-form-item> </el-form> </div> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible1 = false">取 消</el-button> <el-button type="primary" @click="saveTask">确 定</el-button> </span> </el-dialog> <el-dialog title="配置指标和权重" :visible.sync="dialogVisible2"> <div class="modal"> <div class="left"> <div class="setText">累计权重</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" > <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" > <div>{{ ele.reviewItem }}</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">总计</div> <div class="statusText"> {{ scoreList.reduce((total, ele) => total + (ele.weight || 0), 0) }}% </div> </div> </div> <div class="right"> <div class="flex-row jcsb" style="margin-bottom: 10px"> <div style="width: 50%">指标</div> <div class="center" style="width: 50%">权重占比</div> </div> <div> <div v-for="(item, index) in ( scoreList.find((ele) => ele.title == letfValue) || {} ).list" :key="index" style="margin-bottom: 10px" class="flex-row jcsb aic" > <div style="width: 50%">{{ item.reviewItem }}</div> <div class="center" style="width: 50%"> <el-slider v-model="item.weight" :max="20" @change="totalWeight" ></el-slider> <div class="flex-row jcsb scoreBox" style="margin-left: 15px"> <div>0%</div> <div class="scoreText">{{ item.weight }}%</div> <div>20%</div> </div> </div> </div> </div> </div> </div> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible2 = false">取消</el-button> <el-button type="primary" @click="save">保存</el-button> </span> </el-dialog> </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: { taskName: "", taskStatus: "", }, columns: [ { prop: "taskName", label: "任务名称" }, { prop: "peopleNumber", label: "考核人数" }, { prop: "taskStatus", label: "任务状态", type: "status", callback: (value) => { if (value == 1) var color = "#333"; else var color = "#1686d68"; return `<span style="color: ${color}">${ value ? "已过期" : "进行中" }</span>`; }, }, { prop: "createTime", label: "创建时间", type: "status", callback: (value) => { return value.split(" ")[0]; }, }, { prop: "endTime", label: "截至时间", type: "status", callback: (value) => { return value.split(" ")[0]; }, }, { prop: "operation", label: "操作", width: "250", className: "operation-column", }, ], tableData: [], total: 0, userSelectDialogVisible: false, currentSelectedUser: [], pageNum: 1, // 当前页码 pageSize: 10, // 每页条数 statusList: [ { label: "全部", value: "" }, { label: "待评分", value: "0" }, { label: "已完成", value: "1" }, ], dialogVisible1: false, isEdit: false, taskData: { id: "", taskName: "", peopleNumberDetail: "", userIdList: [], endTime: "", peopleNumber: 0, }, rules: { taskName: [ { required: true, message: "请输入活动名称", trigger: "blur" }, { min: 1, max: 20, message: "长度在 3 到 5 个字符", trigger: "blur" }, ], peopleNumberDetail: [ { required: true, message: "请选择考核人员", trigger: "blur" }, ], endTime: [ { required: true, message: "请选择截止时间", trigger: "blur" }, ], }, dialogVisible2: false, letfValue: "", scoreList: [], }; }, watch: { scoreList: { handler(newVal, oldVal) { this.scoreList.forEach((ele) => { ele.weight = ele.list.reduce( (total, ele) => total + (ele.weight || 0), 0 ); }); }, deep: true, }, }, methods: { onSearch() { this.getTaskList(); }, onReset() { Object.keys(this.searchForm).forEach((key) => { this.searchForm[key] = ""; }); this.getTaskList(); }, getTaskList() { taskApi .getTaskList({ ...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.getTaskList(); }, handleCurrentChange(page) { this.pageNum = page; this.getTaskList(); }, openUserSelectDialog() { this.userSelectDialogVisible = true; }, handleUserConfirm(data) { this.taskData.peopleNumberDetail = data .map((ele) => ele.nickName) .join(","); this.taskData.userIdList = data.map((ele) => ele.userId); this.taskData.peopleNumber = data.length; }, handleUserClose() { this.userSelectDialogVisible = false; }, addTask() { this.isEdit = false; this.dialogVisible1 = true; }, editTask(row) { this.isEdit = true; this.dialogVisible1 = true; this.taskData.id = row.id; this.taskData.taskName = row.taskName; this.taskData.peopleNumber = row.peopleNumber; this.taskData.peopleNumberDetail = row.peopleNumberDetail; this.taskData.userIdList = row.userIdList; this.currentSelectedUser = []; (row.userIdList || []).forEach((ele) => { this.currentSelectedUser.push(ele); }); }, setTask(row) { taskApi.getTaskSet(row.id).then((res) => { let objData = {}; res.data.forEach((ele) => { if (!objData[ele.reviewCategory]) objData[ele.reviewCategory] = []; objData[ele.reviewCategory].push(ele); }); this.scoreList = Object.values(objData).map((ele) => ({ title: ele[0].reviewCategory, list: ele, weight: ele.reduce((total, ele) => (ele.weight || 0) + total, 0), })); this.dialogVisible2 = true; }); }, delTask(row) { this.$confirm( "删除任务及绩效数据,该操作不可逆,请谨慎操作", "确认删除任务", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", } ).then(() => { taskApi.delTask(row.id).then((res) => { this.$message({ type: "success", message: "删除成功!", }); this.getTaskList(); }); }); }, saveTask() { this.$refs.taskFormRef.validate((valid) => { if (valid) { if (this.taskData.id) { taskApi.upDateTask(this.taskData).then((res) => { this.$message({ type: "success", message: "修改成功!", }); this.dialogVisible1 = false; this.getTaskList(); }); } else { taskApi.addTask(this.taskData).then((res) => { this.$message({ type: "success", message: "新增成功!", }); this.dialogVisible1 = false; this.getTaskList(); }); } } else { console.log("error submit!!"); return false; } }); }, }, mounted() { this.getTaskList(); }, }; </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: 20px; border-radius: 20px; margin: 15px !important; /* width: 95%; */ } ::v-deep .el-slider__bar { height: 20px; border-radius: 20px; background-color: #ff5722; } ::v-deep .el-slider__button { display: none; } .scoreText { color: #1686d8; } .setText { margin-bottom: 20px; text-align: right; } .leftSub { padding-right: 20px; margin-bottom: 5px; } .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; } </style>