master
xy 3 years ago
parent ca1fbcfd90
commit a3da6dcfea

@ -0,0 +1,33 @@
import request from '@/utils/request'
export function index(params) {
return request({
method: "get",
url: "/api/admin/plan_target/index",
params
})
}
export function show(params) {
return request({
method: "get",
url: "/api/admin/plan_target/show",
params
})
}
export function save(data) {
return request({
method: "post",
url: "/api/admin/plan_target/save",
data
})
}
export function destroy(params) {
return request({
method: "get",
url: "/api/admin/plan_target/destroy",
params
})
}

@ -129,6 +129,9 @@ export default {
},
toggleAllSelection(){
this.$refs.table.toggleAllSelection()
},
doLayout() {
this.$refs['table'].doLayout();
}
},
created() {

@ -135,3 +135,64 @@ export function moneyFormatter(money,precision=2){
export function moneyRecovery(money){
return parseFloat(money.replace(/[^\d\.-]/g, ""));
}
//深拷贝
export function deepCopy(data) {
//string,number,bool,null,undefined,symbol
//object,array,date
if (data && typeof data === "object") {
//针对函数的拷贝
if (typeof data === "function") {
let tempFunc = data.bind(null);
tempFunc.prototype = deepCopy(data.prototype);
return tempFunc;
}
switch (Object.prototype.toString.call(data)) {
case "[object String]":
return data.toString();
case "[object Number]":
return Number(data.toString());
case "[object Boolean]":
return new Boolean(data.toString());
case "[object Date]":
return new Date(data.getTime());
case "[object Array]":
let arr = [];
for (let i = 0; i < data.length; i++) {
arr[i] = deepCopy(data[i]);
}
return arr;
//js自带对象或用户自定义类实例
case "[object Object]":
let obj = {};
for (let key in data) {
//会遍历原型链上的属性方法可以用hasOwnProperty来控制 obj.hasOwnProperty(prop)
obj[key] = deepCopy(data[key]);
}
return obj;
}
} else {
//string,number,bool,null,undefined,symbol
return data;
}
}
export function resetSelect(select) {
let keys = Object.keys(select);
keys.forEach(key => {
if(key === 'page'){
select[key] = 1
}
else if(key === 'page_size'){
select[key] = 10
}
else if(select[key] instanceof Array){
select[key] = []
}
else {
select[key] = ""
}
})
}

@ -286,6 +286,8 @@ export default {
async getDetail() {
const res = await show({ id: this.id });
this.$integrateData(this.form, res);
this.target_type2s = this.target_types?.filter(i => i.id === this.form.target_type_id)[0]?.children
},
submit() {

@ -13,15 +13,16 @@
</div>
<Button style="margin-left: 10px" type="primary"
@click="">重置
@click="resetSelect(select)">重置
</Button>
<Button style="margin-left: 10px" type="primary" @click="getList"></Button>
<Button style="margin-left: 10px" type="primary" @click="select.page = 1,total = 0,getList()"></Button>
<Button style="margin-left: 10px" type="primary" @click="$refs['addPoint'].type = 'add',$refs['addPoint'].show()">新增</Button>
</div>
</slot>
</lx-header>
<xy-table :list="list"
ref="table"
:table-item="table"
:object-span-method="spanMethod"
@editor="row => {
@ -33,7 +34,18 @@
</xy-table>
<div style="display: flex;justify-content: flex-end;">
<Page :total="total" @on-change="" show-elevator show-sizer @on-page-size-change="" />
<Page :total="total"
@on-change="e => {
select.page = e;
getList();
}"
show-elevator
show-sizer
@on-page-size-change="e => {
select.page_size = e;
select.page = 1;
getList();
}" />
</div>
<addPoint ref="addPoint" :target_types="types" :symbol_ids="symbols" :unit_ids="units" @refresh="getList"></addPoint>
@ -44,6 +56,7 @@
import { index,destroy } from "@/api/achievements/points";
import { index as typesIndex } from "@/api/achievements/types";
import { getparameter } from "@/api/system/dictionary"
import { resetSelect } from "@/utils/index"
import addPoint from '@/views/achievements/components/addPoint.vue'
export default {
@ -107,6 +120,7 @@ export default {
}
},
methods: {
resetSelect,
async getTypes() {
const res = await typesIndex({ show_tree:1 })
this.types = res || []
@ -131,9 +145,12 @@ export default {
},
async getList() {
this.pos = this.pos1 = 0;
this.spanArr = [];
this.spanArr1 = [];
const res = await index(this.select)
this.total = res.total
this.list = res.data
console.log(this.list)
for(let i in this.list){
if(i === 0){
@ -203,7 +220,7 @@ export default {
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
if (column.property === "target_type_detail.name") {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
@ -211,7 +228,7 @@ export default {
colspan: _col
}
}
if (columnIndex === 1) {
if (column.property === "target_type2_detail.name") {
const _row = this.spanArr1[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {

@ -61,15 +61,16 @@
<Button class="slot-btns-item" size="small" type="primary" @click="showEditor(scope.row)">
编辑
</Button>
<Button style="margin-left: 10px;" @click="showAdd(scope.row)" v-if="scope.row.pid==0"
<Button @click="showAdd(scope.row)" v-if="scope.row.pid==0"
class="slot-btns-item" size="small" type="info">
下级
</Button>
<Poptip :transfer="true" style="margin-left: 10px;" confirm placement="bottom" title="确认要删除吗"
<Poptip :transfer="true" confirm placement="bottom" title="确认要删除吗"
@on-ok="()=>deleteTable(scope.row)">
<i-button class="slot-btns-item" size="small" type="error">删除
</i-button>
</Poptip>
<Button class="slot-btns-item" size="small" type="primary" @click="$refs['addPoint'].setPlanId(scope.row.id),$refs['addPoint'].show()"></Button>
</div>
</template>
</el-table-column>
@ -86,15 +87,15 @@
<Button class="slot-btns-item" size="small" type="primary" @click="showEditor(scope.row)">
编辑
</Button>
<Button style="margin-left: 10px;" @click="showAdd(scope.row)" v-if="scope.row.pid==0"
<Button @click="showAdd(scope.row)" v-if="scope.row.pid==0"
class="slot-btns-item" size="small" type="info">
下级
</Button>
<Poptip :transfer="true" style="margin-left: 10px;" confirm placement="bottom" title="确认要删除吗"
<Poptip :transfer="true" confirm placement="bottom" title="确认要删除吗"
@on-ok="()=>deleteTable(scope.row)">
<i-button class="slot-btns-item" size="small" type="error">删除
</i-button>
<i-button class="slot-btns-item" size="small" type="error">删除</i-button>
</Poptip>
<Button class="slot-btns-item" size="small" type="primary" @click="$refs['addPoint'].setPlanId(scope.row.id),$refs['addPoint'].show()"></Button>
</div>
</template>
</el-table-column>
@ -320,6 +321,8 @@
<Button type="primary" @click="editorTable"></Button>
</template>
</xy-dialog>
<addPoint ref="addPoint"></addPoint>
</div>
</template>
@ -345,12 +348,15 @@
import {
getparameter
} from "@/api/system/dictionary"
import {
mergeTableRow
} from "@/utils/mergeTableRow"
import addPoint from "./components/addPoint.vue"
export default {
components: {
addPoint
},
data() {
return {
tableHeight: 0,
@ -812,4 +818,15 @@
z-index: 2;
}
}
.slot-btns {
display: flex;
flex-wrap: wrap;
align-content: center;
justify-content: flex-start;
&-item {
margin: 0 6px 4px 0;
}
}
</style>

@ -0,0 +1,397 @@
<template>
<div>
<el-drawer
size="46%"
title="绩效指标"
:visible.sync="isShow"
direction="rtl"
>
<Button shape="circle"
type="primary"
:style="{
'margin':'0 0 10px 20px'
}"
@click="isShowModal = true">
目标选择</Button
>
<xy-table :list="list" :table-item="table">
<template v-slot:btns> </template>
</xy-table>
</el-drawer>
<el-dialog title="绩效指标列表" :visible.sync="isShowModal" width="54%">
<Table
:data="points"
:columns="pointTable"
:loading="loading"
border
size="small"
:span-method="spanMethod"
@on-selection-change="selectionChange"
></Table>
<div style="display: flex; justify-content: center; margin: 10px 0">
<Page :total="pointTotal"
size="small"
show-elevator
show-total
@on-change="e => {
pointSelect.page = e;
getPoints();
}"/>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="isShowModal = false"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</span>
</el-dialog>
<el-dialog :title="evaluateForm.type === 1 ? '年中绩效目标' : '年末绩效目标'" :visible.sync="isShowEvaluate" width="54%">
<el-input v-model="evaluateForm.result" type="textarea" :autosize="{minRows:6}" placeholder="请填写目标"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="isShowModal = false"> </el-button>
<el-button type="primary" @click="submitEvaluate"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { index, save, destroy } from "@/api/budget/planTarget";
import { index as pointIndex } from "@/api/achievements/points";
import { save as evaluateSave } from "@/api/achievements/evaluate"
import { resetSelect } from "@/utils"
export default {
data() {
return {
isShow: false,
list: [],
table: [
{
label: "指标名称",
prop: "target.name",
minWidth: 200
},
{
label: "半年(程)指标值",
prop: "target.half_target",
width: 180
},
{
label: "全年(程)指标值",
prop: "target.year_target",
width: 180
},
{
label: "创建时间",
prop: "created_at",
width: 200,
},
{
label: "操作",
align: "left",
minWidth: 200,
customFn: (row) => {
return (
<div style={
{
'display':'flex',
'align-items':'center',
'flex-wrap':'wrap',
'justify-content':'flex-start'
}
}>
<el-dropdown on={{
['command']:command => {
this.evaluateForm.plan_target_id = row.id
this.evaluateForm.type = command
this.isShowEvaluate = true
}
}}>
<el-button size="mini" type="primary">
绩效目标<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command={1}>年中目标</el-dropdown-item>
<el-dropdown-item command={2}>年末目标</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-popover
style="margin-left: .4em;"
placement="top"
width="160"
trigger="click"
>
<p>确定删除吗</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text">
取消
</el-button>
<el-button
type="primary"
size="mini"
on={{
["click"]: (e) => {
destroy({
id: row.id,
}).then((res) => {
this.$message({
type: "success",
message: "删除成功",
});
this.getList();
});
},
}}
>
确定
</el-button>
</div>
<el-button slot="reference" size="mini" type="danger">
删除
</el-button>
</el-popover>
</div>
);
},
},
],
select: {
page: 1,
page_size: 999,
plan_id: "",
},
loading: false,
isShowModal: false,
pointSelect: {
page: 1,
page_size: 10,
},
points: [],
pointTotal: 0,
spanArr: [],
spanArr1: [],
pos1: 0,
pos: 0,
pointTable: [
{
type: "selection",
width: 56,
align: "center",
},
{
title: "一级指标",
key: "target_type",
render: (h, { row, column, index }) => {
return h("span", {}, row.target_type_detail?.name);
},
minWidth: 180,
align: "center",
},
{
title: "二级指标",
key: "target_type2",
render: (h, { row, column, index }) => {
return h("span", {}, row.target_type2_detail?.name);
},
minWidth: 180,
align: "center",
},
{
title: "三级指标",
key: "name",
minWidth: 180,
align: "center",
},
{
title: "计算符号",
render: (h, { row, column, index }) => {
return h("span", {}, row.symbol_detail?.value);
},
width: 160,
align: "center",
},
{
title: "半年(程)指标值",
key: "half_target",
width: 200,
align: "center",
},
{
title: "全年(程)指标值",
key: "year_target",
width: 200,
align: "center",
},
{
title: "单位",
render: (h, { row, column, index }) => {
return h("span", {}, row.unit_detail?.value);
},
width: 160,
align: "center",
},
],
selections: [], //
isShowEvaluate: false,
evaluateForm: {
result: "",
type: 1,
file_ids: [],
plan_target_id: ""
}
};
},
methods: {
show() {
this.isShow = true;
},
hidden() {
this.isShow = false;
},
getPlanId() {
return this.select.plan_id;
},
setPlanId(plan_id) {
this.select.plan_id = plan_id;
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (column.key === "target_type") {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
if (column.key === "target_type2") {
const _row = this.spanArr1[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
selectionChange(selection) {
this.selections = Array.from(
new Set(
selection.map((item) => item.id)
)
);
console.log(this.selections);
},
async getList() {
this.pos = this.pos1 = 0;
this.spanArr = [];
this.spanArr1 = [];
const res = await index(this.select);
this.list = res.data;
},
async getPoints() {
this.loading = true;
try {
const res = await pointIndex(this.pointSelect);
let selectedIds = Array.from(new Set(this.list.map((item) => item.target_id)));
this.points = res.data.map(item => {
return {
...item,
_checked: !!selectedIds.find(i => i === item.id) || !!this.selections.find(i => i === item.id),
_disabled: !!selectedIds.find(i => i === item.id),
}
});
this.pointTotal = res.total;
for (let i in this.points) {
if (i === 0) {
this.spanArr.push(1);
this.pos = 0;
this.spanArr1.push(1);
this.pos1 = 0;
} else {
if (
this.points[i]?.target_type_detail?.name ===
this.points[i - 1]?.target_type_detail?.name
) {
this.spanArr[this.pos] += 1;
this.spanArr.push(0);
} else {
this.spanArr.push(1);
this.pos = i;
}
if (
this.points[i]?.target_type2_detail?.name ===
this.points[i - 1]?.target_type2_detail?.name
) {
this.spanArr1[this.pos1] += 1;
this.spanArr1.push(0);
} else {
this.spanArr1.push(1);
this.pos1 = i;
}
}
}
this.loading = false;
} catch (err) {
this.loading = false;
}
},
submit() {
Promise.all(
this.selections.map((target_id) => {
return save({
target_id,
plan_id: this.getPlanId(),
});
})
).then((res) => {
this.getList();
this.isShowModal = false;
});
},
submitEvaluate() {
evaluateSave(this.evaluateForm).then(res => {
this.$message({
type: 'success',
message: "保存成功"
})
this.isShowEvaluate = false;
})
}
},
computed: {},
watch: {
isShow(val) {
if (val) {
this.getList();
} else {
}
},
isShowModal(val) {
if(val){
this.getPoints();
}else{
this.selections = [];
resetSelect(this.pointSelect);
this.points = [];
this.pointTotal = 0;
}
}
},
};
</script>
<style scoped lang="scss"></style>
Loading…
Cancel
Save