456 lines
14 KiB
Vue
456 lines
14 KiB
Vue
<!-- -->
|
||
<template>
|
||
<div class="goals">
|
||
<SmallNav />
|
||
<div class="goals-content boderAndRadius">
|
||
<div class="goals-content-name">
|
||
<InfoHeader :obj="{
|
||
src:obj.avatar,
|
||
name:obj.staffName,
|
||
departmentName:obj.departmentName
|
||
}" />
|
||
</div>
|
||
<div class="goals-content-tabbar">
|
||
<el-tabs :value="activeId">
|
||
<el-tab-pane v-for="(i,index) in obj.recortModelDtos"
|
||
:key="i.id"
|
||
:label="i.name + ' ( '+( i.maxCount===null?(handleNumber(i)):(handleNumber(i)+'/'+i.maxCount))+' ) '"
|
||
:name="String(i.id)">
|
||
<div class="goals-content-tabbar-table">
|
||
<div class="goals-content-tabbar-table-header commonFont">
|
||
<span style="width:30%">指标名称</span>
|
||
<span class="kaohe"
|
||
style="width:30%">考核标准</span>
|
||
<span style="width:30%">权重</span>
|
||
<span style="width:10%">操作</span>
|
||
</div>
|
||
<div style="justify-content:center;"
|
||
v-if="handleFilter(i.detailDtos).length===0"
|
||
class="goals-content-tabbar-table-content commonFont items">
|
||
暂无指标
|
||
</div>
|
||
<draggable v-model="i.tagetLibItems"
|
||
:options='options1'>
|
||
<div class="goals-content-tabbar-table-content commonFont items"
|
||
v-for="(j,indexJ) in handleFilter(i.detailDtos)"
|
||
:key="indexJ">
|
||
<div style="width:30%"
|
||
class="my-handle"><img style="width:20px;height:20px;"
|
||
src="@/assets/img/yidong.png"
|
||
alt="">{{j.target}}</div>
|
||
<div style="width:30%"
|
||
class="kaohe">
|
||
<pre>{{j.keyResult}}</pre>
|
||
</div>
|
||
<div style="width:30%">{{ Math.round((j.checkWeight * 100)*1000)/1000}}%</div>
|
||
<div style="width:10%">
|
||
<el-button @click="hanidleEdit(j,indexJ,index)"
|
||
type="text"
|
||
size="small">
|
||
编辑
|
||
</el-button>
|
||
<el-button @click="handleDelateWeidu(j,indexJ,index)"
|
||
type="text"
|
||
size="small">
|
||
删除
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
</draggable>
|
||
<div style=" padding: 10px;font-size:16px;"
|
||
class="commonFont">
|
||
<div>
|
||
业务指标权重:{{handleGetWeight(i)}}% <span v-if="i.weight !== null">/{{Math.round((i.weight * 100)*1000)/1000}}%</span>
|
||
</div>
|
||
<div>
|
||
所有指标总权重: {{ handleGetWeight1()}}%
|
||
</div>
|
||
</div>
|
||
<div style=" padding: 10px;">
|
||
<!-- <el-button size="mini" plain>选择指标项</el-button> -->
|
||
<el-button @click="hanidleEdit(i,-1,index)"
|
||
type="primary"
|
||
icon="el-icon-plus"
|
||
size="small"
|
||
plain>增加指标项</el-button>
|
||
</div>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
</div>
|
||
<popup-right v-if="showIndicators"
|
||
@cancel='handleCancelZhibiao'
|
||
@submit="handleSubmitZhibiao"
|
||
:title="zhibiaoTitle">
|
||
<div slot="content"
|
||
class="weiduManage">
|
||
<el-form label-position="left"
|
||
ref="formIndicators"
|
||
:model="formIndicators"
|
||
:rules="ruleIndicators"
|
||
label-width="180px">
|
||
<el-form-item label="指标类型">
|
||
<el-select v-model="formIndicators.type"
|
||
disabled
|
||
placeholder="请选择维度类型">
|
||
<el-option v-for="i in dimensionsList"
|
||
:key="i.id"
|
||
:label="i.name"
|
||
:value="i.id"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item prop="target"
|
||
label='指标名称'>
|
||
<el-input clearable
|
||
size="small"
|
||
v-model="formIndicators.target"></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="考核标准"
|
||
prop="keyResult">
|
||
<el-input size="small"
|
||
clearable
|
||
:rows="24"
|
||
type="textarea"
|
||
v-model="formIndicators.keyResult"></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="权重"
|
||
prop="weight">
|
||
<el-input size="small"
|
||
@blur="$handleBlur('formIndicators.checkWeight')"
|
||
@input.native="$handleInputInt('formIndicators.checkWeight')"
|
||
v-model="formIndicators.checkWeight">
|
||
<template slot="append">%</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
</popup-right>
|
||
<div class="goals-bottom">
|
||
<div class="goals-bottom-content">
|
||
<el-button size='small'
|
||
@click="handleSaveDetail()"
|
||
plain>暂存</el-button>
|
||
<el-button size='small'
|
||
type="primary"
|
||
@click="handleGetNext">提交</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import SmallNav from '@/components/kpi-layout/SmallNav'
|
||
import InfoHeader from '@/components/InfoHeader'
|
||
import PopupRight from '@/components/PopupRight'
|
||
import draggable from 'vuedraggable'
|
||
import { getDimensions } from '@/api/data'
|
||
import { apiResultGetDetail, apiSaveDetail, apiSaveapproval } from '@/api/assessment'
|
||
export default {
|
||
data () {
|
||
return {
|
||
zhibiaoTitle: '添加指标',
|
||
showIndicators: false,
|
||
dimensionsList: [],
|
||
formIndicators: {},
|
||
ruleIndicators: {
|
||
target: [{
|
||
required: true,
|
||
message: '请输入指标名称',
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
keyResult: [{
|
||
required: true,
|
||
message: '请输入考核标准',
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
checkWeight: [{
|
||
required: true,
|
||
message: '请输入权重大小',
|
||
trigger: 'blur'
|
||
}
|
||
]
|
||
},
|
||
activeId: null,
|
||
obj: {
|
||
recortModelDto: []
|
||
},
|
||
options1: {
|
||
group: 'names',
|
||
draggable: '.items',
|
||
handle: '.my-handle',
|
||
scroll: true,
|
||
sort: true, // 内部排序列表
|
||
delay: 0, // 以毫秒为单位定义排序何时开始。
|
||
touchStartThreshold: 0, // px,在取消延迟拖动事件之前,点应该移动多少像素?
|
||
disabled: false, // 如果设置为真,则禁用sortable。
|
||
store: null, // @see Store
|
||
animation: 150 // ms, 动画速度运动项目排序时,' 0 ' -没有动画。
|
||
}
|
||
}
|
||
},
|
||
components: {
|
||
SmallNav,
|
||
InfoHeader,
|
||
draggable,
|
||
PopupRight
|
||
},
|
||
computed: {},
|
||
beforeMount () { },
|
||
mounted () {
|
||
this.handleGetDimensions()
|
||
this.handleGetTbale()
|
||
},
|
||
methods: {
|
||
handleNumber (item) {
|
||
return item.detailDtos ? item.detailDtos.filter(i => !i.isDelete).length : 0
|
||
},
|
||
async handleGetNext () {
|
||
const arr = this.handleFilter(this.obj.recortModelDtos)
|
||
if (arr.some(i => i.weight === null)) {
|
||
let weight = 0
|
||
let maxWeight = 0
|
||
const nullArray = arr.map(i => {
|
||
i.detailDtos.map(j => {
|
||
if (i.weight === null) maxWeight += j.checkWeight
|
||
weight += j.checkWeight
|
||
})
|
||
})
|
||
if (weight !== 1) {
|
||
const noWeightArr = arr.filter(i => i.weight === null)
|
||
let str = noWeightArr.map(i => i.name).join(',')
|
||
this.$message.error(str + '维度内的权重和必须为100%!')
|
||
return
|
||
}
|
||
} else {
|
||
for (let i in arr) {
|
||
if (arr[i].detailDtos.length > 0 && !arr[i].isTrue) {
|
||
this.$message.error(arr[i].name + '维度内的权重和必须为' + Math.round((arr[i].weight * 100) * 1000) / 1000)
|
||
return
|
||
}
|
||
}
|
||
}
|
||
const obj = { status: 1, menuName: '制定了' }
|
||
const params = Object.assign({}, { resultRecordId: this.$route.query.id || '' }, obj)
|
||
let res = await apiSaveapproval(params)
|
||
console.log("🚀 ~ file: index.vue ~ line 238 ~ handleGetNext ~ res", res)
|
||
if (res.code !== 200) {
|
||
this.$message.error(res.msg || '出错了 ')
|
||
return
|
||
}
|
||
this.obj.commentId = res.commentId
|
||
let res1 = await apiSaveDetail(this.obj)
|
||
if (res1.code !== 200) {
|
||
this.$message.error(res1.msg)
|
||
return
|
||
}
|
||
this.$message({
|
||
message: res.msg,
|
||
type: 'success'
|
||
})
|
||
// history.go(-1)
|
||
},
|
||
handleGetWeight1 () {
|
||
let num = 0
|
||
this.obj.recortModelDtos.map(i => {
|
||
i.detailDtos.filter(i => !i.isDelete).map(i => {
|
||
num += i.checkWeight
|
||
})
|
||
})
|
||
return Math.round((num * 100) * 1000) / 1000
|
||
},
|
||
handleGetWeight (arr) {
|
||
const weight = arr.detailDtos.filter(i => !i.isDelete).reduce((num, i) => {
|
||
num += i.isDelete !== 1 ? i.checkWeight : 0
|
||
return num
|
||
}, 0)
|
||
arr.isTrue = (Math.round((weight * 100) * 1000) / 1000) === (Math.round((arr.weight * 100) * 1000) / 1000)
|
||
return Math.round((weight * 100) * 1000) / 1000
|
||
},
|
||
async handleSaveDetail (params = this.obj) {
|
||
let res = await apiSaveDetail(params)
|
||
if (res.code !== 200) {
|
||
this.$message.error(res.msg)
|
||
return
|
||
}
|
||
this.$message({
|
||
message: res.msg,
|
||
type: 'success'
|
||
})
|
||
this.handleGetTbale()
|
||
},
|
||
// 获取维度类型
|
||
async handleGetDimensions () {
|
||
try {
|
||
let res = await getDimensions()
|
||
if (res.code !== 200) {
|
||
this.dimensionsList = []
|
||
return
|
||
}
|
||
res = res.data
|
||
this.dimensionsList = res
|
||
} catch (error) {
|
||
this.$message.error(error.msg)
|
||
}
|
||
},
|
||
handleCancelZhibiao () {
|
||
this.showIndicators = false
|
||
},
|
||
handleSubmitZhibiao () {
|
||
this.$refs.formIndicators.validate((v) => {
|
||
if (v) {
|
||
if (this.formIndicators.index === -1) {
|
||
this.obj.recortModelDtos[this.formIndicators.dazhibiaoIndex].detailDtos.push(Object.assign({}, this.formIndicators, { checkWeight: this.formIndicators.checkWeight / 100 }))
|
||
} else {
|
||
this.obj.recortModelDtos[this.formIndicators.dazhibiaoIndex].detailDtos[this.formIndicators.index] = Object.assign({}, this.formIndicators, { checkWeight: this.formIndicators.checkWeight / 100 })
|
||
}
|
||
this.showIndicators = false
|
||
}
|
||
})
|
||
},
|
||
// 编辑
|
||
hanidleEdit (item, index, type) {
|
||
if (item.maxCount !== null) {
|
||
const len = this.handleNumber(item)
|
||
if (item.maxCount <= len) {
|
||
this.$message.info('指标数量不能大于' + item.maxCount)
|
||
return
|
||
}
|
||
}
|
||
if (index === -1) {
|
||
this.formIndicators = {
|
||
checkWeight: 0
|
||
}
|
||
} else {
|
||
this.formIndicators = Object.assign({}, item)
|
||
this.formIndicators.checkWeight = this.formIndicators.checkWeight * 100
|
||
}
|
||
this.formIndicators.dazhibiaoIndex = type
|
||
this.formIndicators.index = index
|
||
this.formIndicators.type = item.type
|
||
this.showIndicators = true
|
||
},
|
||
handleDelateWeidu (item, index, type) {
|
||
if (item.id) {
|
||
item.isDelete = 1
|
||
this.$forceUpdate()
|
||
return
|
||
}
|
||
this.obj.recortModelDtos[type].detailDtos = this.obj.recortModelDtos[type].detailDtos.filter(i => i !== item)
|
||
this.$forceUpdate()
|
||
},
|
||
handleFilter (item) {
|
||
return item ? item.filter(i => !i.isDelete) : []
|
||
},
|
||
async handleGetTbale (id = this.$route.query.id) {
|
||
let res = await apiResultGetDetail({ id })
|
||
if (res.code !== 200) return
|
||
this.obj = res.data
|
||
this.activeId = String(res.data.recortModelDtos[0].id)
|
||
}
|
||
},
|
||
watch: {}
|
||
|
||
}
|
||
|
||
</script>
|
||
|
||
<style lang='less' scoped>
|
||
.goals {
|
||
.kaohe {
|
||
flex: none;
|
||
width: 500px;
|
||
display: block;
|
||
pre {
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
word-break: break-all;
|
||
}
|
||
}
|
||
margin-bottom: 100px;
|
||
position: relative;
|
||
.my-handle {
|
||
cursor: move;
|
||
display: flex;
|
||
align-items: center;
|
||
img {
|
||
margin-right: 10px;
|
||
}
|
||
}
|
||
&-bottom {
|
||
position: fixed;
|
||
height: 60px;
|
||
border-top: 1px solid @borderColor;
|
||
padding: 0 80px;
|
||
width: 100%;
|
||
background: #fff;
|
||
bottom: 0;
|
||
left: 0;
|
||
&-content {
|
||
padding: 0 80px;
|
||
margin: 0 auto;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
&-content {
|
||
padding: 28px;
|
||
&-name {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
&-title {
|
||
margin: 0 0 10px 0;
|
||
display: flex;
|
||
align-items: center;
|
||
&-img {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
&-right {
|
||
margin-left: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
&-tabbar {
|
||
&-table {
|
||
&-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
height: 60px;
|
||
background: rgb(231, 231, 231);
|
||
border-bottom: 1px solid @borderColor;
|
||
span {
|
||
padding: 0 0 0 20px;
|
||
}
|
||
}
|
||
&-content {
|
||
display: flex;
|
||
padding: 20px 0;
|
||
// align-items: center;
|
||
// height: 60px;
|
||
border-bottom: 1px solid @borderColor;
|
||
justify-content: space-between;
|
||
div {
|
||
padding: 0 0 0 20px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|