出差报销 资金明细

master
lion 2 years ago
parent f6280c8a9d
commit 4c032c1f2f

@ -3,7 +3,7 @@ import request from "@/utils/request";
export function getActual(params){ export function getActual(params){
return request({ return request({
method:'get', method:'get',
url:'/api/ht/contract-plan-act-links/index', url:'/api/ht/contract-plan-act-temp/index',
params params
}) })
} }
@ -11,7 +11,7 @@ export function getActual(params){
export function delActual(params){ export function delActual(params){
return request({ return request({
method:'get', method:'get',
url:'/api/ht/contract-plan-act-links/destroy', url:'/api/ht/contract-plan-act-temp/destroy',
params params
}) })
} }
@ -19,7 +19,7 @@ export function delActual(params){
export function editorActual(data){ export function editorActual(data){
return request({ return request({
method:'post', method:'post',
url:'/api/ht/contract-plan-act-links/save', url:'/api/ht/contract-plan-act-temp/save',
data data
}) })
} }
@ -27,7 +27,15 @@ export function editorActual(data){
export function detailActual(params){ export function detailActual(params){
return request({ return request({
method:'get', method:'get',
url:"/api/ht/contract-plan-act-links/show", url:"/api/ht/contract-plan-act-temp/show",
params params
}) })
} }
export function carryActual(data){
return request({
method:'post',
url:"/api/ht/contract-plan-act-temp/carry",
data
})
}

@ -57,7 +57,12 @@
width: 120, width: 120,
align: 'left' align: 'left'
}, },
{
prop: 'zijinlaiyuan',
label: '资金来源',
minWidth: 240,
align: 'left'
},
{ {
prop: 'flow.title', prop: 'flow.title',
label: '流程名称', label: '流程名称',
@ -134,23 +139,23 @@
isSelect: false // 添加选中状态字段 isSelect: false // 添加选中状态字段
}; };
const innerData = originalData[xingming_details]; const innerData = originalData[xingming_details];
innerData.map(item=>{ innerData.map(item => {
item.isSelect = false item.isSelect = false
}) })
person.children.push(...innerData) person.children.push(...innerData)
// const source = { // const source = {
// id: Math.random(), // id: Math.random(),
// name: '', // name: '',
// children: innerData.map((item) => ({ // children: innerData.map((item) => ({
// ...item, // ...item,
// name: item.xingming_detail, // name: item.xingming_detail,
// parent: source, // 指向当前父级 // parent: source, // 指向当前父级
// isSelect: false // 添加选中状态字段 // isSelect: false // 添加选中状态字段
// })), // })),
// parent: person, // 指向当前父级 // parent: person, // 指向当前父级
// isSelect: false // 添加选中状态字段 // isSelect: false // 添加选中状态字段
// }; // };
// person.children.push(source); // person.children.push(source);
result.push(person); result.push(person);
} }

@ -1,10 +1,6 @@
<template> <template>
<div style="padding: 0 20px"> <div style="padding: 0 20px">
<lx-header <lx-header icon="md-apps" style="margin-bottom: 10px; border: 0px; margin-top: 15px" text="实际使用金额">
icon="md-apps"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
text="实际使用金额"
>
<div slot="content"></div> <div slot="content"></div>
<slot> <slot>
<div class="selects"> <div class="selects">
@ -23,45 +19,27 @@
<Button style="margin-left: 10px" type="primary" @click="getList" <Button style="margin-left: 10px" type="primary" @click="getList"
>查询</Button >查询</Button
> --> > -->
<Button <Button style="margin-left: 10px" type="primary" @click="
style="margin-left: 10px"
type="primary"
@click="
($refs['addActual'].type = 'add'), $refs['addActual'].show() ($refs['addActual'].type = 'add'), $refs['addActual'].show()
" ">新增</Button>
>新增</Button
>
</div> </div>
</slot> </slot>
</lx-header> </lx-header>
<xy-table <xy-table :list="list" :table-item="table">
:list="list"
:table-item="table"
>
<template #btns> <template #btns>
<el-table-column :fixed="$store.getters.device === 'mobile'?false:'right'" label="操作" align="left" width="200"> <el-table-column :fixed="$store.getters.device === 'mobile'?false:'right'" label="操作" align="left" width="200">
<template #default="{ row }"> <template #default="{ row }">
<div style="display: flex;align-items: flex-start;"> <div style="display: flex;align-items: flex-start;">
<Button <Button style="margin-right: 4px;" v-if="calculateTotalUseMoney(row.plan_act_links)<parseFloat(row.money)" ghost size="small" type="primary" @click="execute(row)">确认执行</Button>
ghost <Button style="margin-right: 4px;" ghost size="small" type="primary" @click="
size="small"
type="primary"
@click="
($refs['addActual'].id = row.id), ($refs['addActual'].id = row.id),
($refs['addActual'].type = 'editor'), ($refs['addActual'].type = 'editor'),
$refs['addActual'].show() $refs['addActual'].show()
" ">编辑</Button>
>编辑</Button <Poptip :transfer="true" confirm placement="bottom"
> :title="row.plan_act_links.length>0?'已有执行记录,确认要连同执行记录一同删除?':'确认要删除吗?'" @on-ok="destroy(row)">
<Poptip <Button size="small" type="error" ghost>删除</Button>
:transfer="true"
confirm
placement="bottom"
title="确认要删除吗"
@on-ok="destroy(row)"
>
<Button style="margin-left: 4px;" size="small" type="error" ghost>删除</Button>
</Poptip> </Poptip>
</div> </div>
</template> </template>
@ -70,94 +48,119 @@
</xy-table> </xy-table>
<div style="display: flex; justify-content: flex-end"> <div style="display: flex; justify-content: flex-end">
<Page <Page :total="total" @on-change="e => {
:total="total"
@on-change="e => {
select.page = e; select.page = e;
getList() getList()
}" }" show-elevator show-sizer @on-page-size-change="e => {
show-elevator
show-sizer
@on-page-size-change="e => {
select.page = 1; select.page = 1;
select.page_size = e; select.page_size = e;
getList(); getList();
}" }" />
/>
</div> </div>
<addActual <addActual :plan_department_ids="depts" ref="addActual" @refresh="getList"></addActual>
:plan_department_ids="depts" <exeActual ref="exeActual" @refresh="getList"></exeActual>
ref="addActual"
@refresh="getList"
></addActual>
</div> </div>
</template> </template>
<script> <script>
import { getActual, delActual } from "@/api/budget/actual"; import {
import addActual from "./components/addActual.vue"; getActual,
export default { delActual,
components: { } from "@/api/budget/actual";
addActual, import addActual from "./components/addActual.vue";
}, import exeActual from "./components/exeActual.vue";
data() { export default {
return { components: {
depts: [], addActual,
select: { exeActual
page: 1, },
page_size: 10, data() {
}, return {
total: 0, depts: [],
table: [ select: {
{ page: 1,
label: "资金来源所属年份", page_size: 10,
prop: "plan.year",
width: 180,
},
{
label: "资金来源",
prop: "plan.name",
// width: 180,
}, },
{ visible: false,
label: "使用金额", total: 0,
prop: "use_money", table: [{
width: 200, label: "资金来源所属年份",
} prop: "plan.year",
], width: 120,
list: [], },
}; {
}, label: "事由",
methods: { prop: "reason",
async getList() { width: 180,
const res = await getActual(this.select); align: 'left'
this.list = res.data; },
this.total = res.total || 0; {
label: "资金来源",
prop: "plan.name",
align: 'left'
// width: 180,
},
{
label: "金额",
prop: "money",
width: 180,
},
{
label: "已使用金额",
prop: "use_money",
width: 180,
formatter: (row, v2, value) => {
return this.calculateTotalUseMoney(row.plan_act_links)
}
}
],
list: [],
};
}, },
destroy (row) { methods: {
delActual({ async getList() {
id: row.id const res = await getActual(this.select);
}).then(res => { this.list = res.data;
this.$message({ this.total = res.total || 0;
type: 'success', },
message: '删除成功' calculateTotalUseMoney(plan_act_links) {
let total = 0;
for (let i = 0; i < plan_act_links.length; i++) {
const useMoney = parseFloat(plan_act_links[i].use_money);
if (!isNaN(useMoney)) {
total += useMoney;
}
}
return parseFloat(total).toFixed(2);
},
destroy(row) {
delActual({
id: row.id
}).then(res => {
this.$message({
type: 'success',
message: '删除成功'
})
this.getList()
}) })
this.getList() },
}) execute(row) {
} this.$refs.exeActual.setForm(row.id,row.plan_act_links)
}, this.$refs.exeActual.isShow = true
computed: {}, }
created() { },
this.getList(); computed: {},
}, created() {
}; this.getList();
},
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.selects { .selects {
display: flex; display: flex;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
} }
</style> </style>

@ -1,240 +1,252 @@
<template> <template>
<div> <div>
<xy-dialog <xy-dialog ref="dialog" :is-show.sync="isShow" type="form" :title="type === 'add' ? '新增实际使用金额' : '编辑实际使用金额'"
ref="dialog" :form="form" :rules="rules" @submit="submit">
:is-show.sync="isShow" <template v-slot:reason>
type="form" <div class="xy-table-item">
:title="type === 'add' ? '新增实际使用金额' : '编辑实际使用金额'" <div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px">*</span>事由:
:form="form" </div>
:rules="rules" <div class="xy-table-item-content">
@submit="submit" <el-input v-model="form.reason" clearable placeholder="请输入事由" style="width: 300px"></el-input>
> </div>
</div>
</template>
<template v-slot:plan_id> <template v-slot:plan_id>
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label"> <div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px" <span style="color: red; font-weight: 600; padding-right: 4px">*</span>
>*</span
>
资金来源: 资金来源:
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<div class="planTitle" @click="$refs.actualPicker.isShow=true">{{form.plan_title}}</div> <div class="planTitle" @click="$refs.actualPicker.isShow=true">{{form.plan_title}}</div>
<!-- <el-input
v-model="form.plan_title"
disabled
clearable
placeholder="请输入备注"
style="width: 300px"
@click="$refs.actualPicker.isShow=true"
></el-input> -->
</div> </div>
</div> </div>
</template> </template>
<template v-slot:use_money>
<template v-slot:money>
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px" <div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px">*</span>金额:
>*</span </div>
>使用金额 :</div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-input <el-input v-model="form.money" clearable placeholder="请输入金额" style="width: 300px"></el-input>
v-model="form.use_money"
clearable
placeholder="请输入备注"
style="width: 300px"
></el-input>
</div> </div>
</div> </div>
</template> </template>
<!-- <template v-slot:use_money>
<div class="xy-table-item">
<div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px">*</span>已使用金额:
</div>
<div class="xy-table-item-content">
<el-input v-model="form.use_money" clearable placeholder="请输入已使用金额" style="width: 300px"></el-input>
</div>
</div>
</template> -->
</xy-dialog> </xy-dialog>
<actualPicker ref="actualPicker" @refresh="getPlanId"></actualPicker> <actualPicker ref="actualPicker" @refresh="getPlanId"></actualPicker>
</div> </div>
</template> </template>
<script> <script>
import { editorActual, detailActual } from "@/api/budget/actual"; import {
import actualPicker from "@/components/PlanPicker/actualPicker.vue" editorActual,
export default { detailActual
components:{ } from "@/api/budget/actual";
actualPicker import actualPicker from "@/components/PlanPicker/actualPicker.vue"
}, export default {
data() { components: {
return { actualPicker
isShow: false, },
id: "", data() {
type: "", return {
form: { isShow: false,
plan_id:'', id: "",
use_money:'', type: "",
plan_title:'' form: {
}, reason: '',
rules: { plan_id: '',
plan_id: [ money: '',
{ // use_money: '',
plan_title: ''
},
rules: {
reason: [{
required: true,
message: "请填写事由",
}],
plan_id: [{
required: true, required: true,
message: "请选择资金来源", message: "请选择资金来源",
}, }],
], money:[{
use_money: [
{
required: true, required: true,
message: "请填写使用金额", message: "请填写金额",
}, }],
], // use_money: [{
}, // required: true,
}; // message: "请填写已使用金额",
}, // }],
methods: { },
show() {
this.isShow = true;
},
hidden() {
this.isShow = false;
},
init() {
this.form = {
plan_id:'',
use_money:''
};
},
setForm(key = [], value = []) {
if (key instanceof Array) {
key.forEach((key, index) => {
this.form[key] = value[index] ?? "";
});
} }
if (typeof key === "string") {
this.form[key] = value;
}
if (!key) {
this.init();
}
},
async getDetail() {
const res = await detailActual({ id: this.id });
this.$integrateData(this.form, res);
this.form.plan_title = res.plan?res.plan.name:''
}, },
getPlanId(e){ methods: {
console.log("e",e) show() {
this.form.plan_id = e.plan_id?e.plan_id:'' this.isShow = true;
this.form.plan_title = e.plan_title?e.plan_title:'' },
}, hidden() {
submit() { this.isShow = false;
if (this.type === "add") { },
if (this.form.hasOwnProperty("id")) { init() {
delete this.form.id; this.form = {
reason: '',
plan_id: '',
money:'',
// use_money: '',
plan_title: ''
};
},
setForm(key = [], value = []) {
if (key instanceof Array) {
key.forEach((key, index) => {
this.form[key] = value[index] ?? "";
});
} }
} if (typeof key === "string") {
if (this.type === "editor") { this.form[key] = value;
Object.defineProperty(this.form, "id", { }
value: this.id, if (!key) {
enumerable: true, this.init();
configurable: true, }
writable: true, },
async getDetail() {
const res = await detailActual({
id: this.id
}); });
} this.$integrateData(this.form, res);
editorActual(this.form).then((res) => { this.form.plan_title = res.plan ? res.plan.name : ''
this.$message({ },
type: "success", getPlanId(e) {
message: console.log("e", e)
this.type === "add" this.form.plan_id = e.plan_id ? e.plan_id : ''
? "新增实际使用金额" this.form.plan_title = e.plan_title ? e.plan_title : ''
: "编辑实际使用金额" + "成功", },
submit() {
if (this.type === "add") {
if (this.form.hasOwnProperty("id")) {
delete this.form.id;
}
}
if (this.type === "editor") {
Object.defineProperty(this.form, "id", {
value: this.id,
enumerable: true,
configurable: true,
writable: true,
});
}
editorActual(this.form).then((res) => {
this.$message({
type: "success",
message: this.type === "add" ?
"新增资金调节记录" :
"编辑资金调节记录" + "成功",
});
this.isShow = false;
this.$emit("refresh");
}); });
this.isShow = false; },
this.$emit("refresh");
});
}, },
}, watch: {
watch: { isShow(val) {
isShow(val) { if (val) {
if (val) { if (this.type === "editor") {
if (this.type === "editor") { this.getDetail();
this.getDetail(); }
} else {
this.id = "";
this.type = "";
this.init();
this.$refs["dialog"].clearValidate();
delete this.form.id;
} }
} else { },
this.id = "";
this.type = "";
this.init();
this.$refs["dialog"].clearValidate();
delete this.form.id;
}
}, },
}, };
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.xy-table-item-label{ .xy-table-item-label {
width: 180px; width: 180px;
} }
::v-deep .el-input__inner {
text-align: left; ::v-deep .el-input__inner {
} text-align: left;
::v-deep .planTitle{ }
width:300px;
display: flex; ::v-deep .planTitle {
background-color: #FFF; width: 300px;
background-image: none; display: flex;
border-radius: 4px; background-color: #FFF;
border: 1px solid #DCDFE6; background-image: none;
-webkit-box-sizing: border-box; border-radius: 4px;
box-sizing: border-box; border: 1px solid #DCDFE6;
color: #606266; -webkit-box-sizing: border-box;
display: inline-block; box-sizing: border-box;
font-size: inherit; color: #606266;
height: 40px; display: inline-block;
line-height: 40px; font-size: inherit;
outline: 0; height: 40px;
padding: 0 15px; line-height: 40px;
} outline: 0;
.img__delete { padding: 0 15px;
transform: scale(0.8, 0.8); }
.img__delete {
transform: scale(0.8, 0.8);
position: absolute; position: absolute;
top: 4px; top: 4px;
right: 4px; right: 4px;
} }
::v-deep .avatar-uploader .el-upload { ::v-deep .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
::v-deep .avatar-uploader .el-upload:hover { ::v-deep .avatar-uploader .el-upload:hover {
border-color: #338de3; border-color: #338de3;
} }
::v-deep .el-upload--picture-card { ::v-deep .el-upload--picture-card {
font-size: 28px; font-size: 28px;
color: #8c939d; color: #8c939d;
width: 80px !important; width: 80px !important;
height: 80px !important; height: 80px !important;
line-height: 80px !important; line-height: 80px !important;
text-align: center; text-align: center;
} }
::v-deep .avatar-uploader-icon { ::v-deep .avatar-uploader-icon {
font-size: 28px; font-size: 28px;
color: #8c939d; color: #8c939d;
width: 80px !important; width: 80px !important;
height: 80px !important; height: 80px !important;
line-height: 80px !important; line-height: 80px !important;
text-align: center; text-align: center;
} }
::v-deep .avatar { ::v-deep .avatar {
width: 80px !important; width: 80px !important;
display: block; display: block;
border-radius: 6px; border-radius: 6px;
} }
::v-deep .el-input__inner { ::v-deep .el-input__inner {
text-align: left; text-align: left;
} }
</style> </style>

@ -0,0 +1,177 @@
<template>
<div>
<xy-dialog ref="dialog" :is-show.sync="isShow" type="form" title="确认执行" :form="form" :rules="rules"
@submit="submit">
<template v-slot:use_money>
<div class="xy-table-item">
<div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px">*</span>使用金额:
</div>
<div class="xy-table-item-content">
<el-input v-model="form.use_money" clearable placeholder="请输入本次使用金额" style="width: 300px"></el-input>
</div>
</div>
</template>
<template v-slot:plan_act_links>
<div class="xy-table-item">
<div class="xy-table-item-label"><span style="color: red; font-weight: 600; padding-right: 4px"></span>执行记录:
</div>
<div class="xy-table-item-content">
<xy-table style="width:500px" :list="form.plan_act_links" :table-item="table">
<template #btns>
<div></div>
</template>
</xy-table>
</div>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import {
carryActual
} from "@/api/budget/actual";
export default {
components: {},
data() {
return {
isShow: false,
form: {
use_money: '',
plan_act_links: '',
contract_plan_act_temp_id: ''
},
table: [{
label: "使用金额",
prop: "use_money",
}, {
label: "执行时间",
prop: "created_at",
width: 180,
}],
rules: {
use_money: [{
required: true,
message: "请填写使用金额",
}],
},
}
},
methods: {
show() {
this.isShow = true;
},
hidden() {
this.isShow = false;
},
init() {
this.form = {
use_money: '',
plan_act_links: [],
contract_plan_act_temp_id: ''
};
},
setForm(contract_plan_act_temp_id, plan_act_links) {
this.form.contract_plan_act_temp_id = contract_plan_act_temp_id
this.form.plan_act_links = plan_act_links
},
submit() {
carryActual(this.form).then((res) => {
this.$message({
type: "success",
message: "执行成功",
});
this.isShow = false;
this.$emit("refresh");
});
},
},
watch: {
isShow(val) {
if (val) {
} else {
this.init();
this.$refs["dialog"].clearValidate();
}
},
},
};
</script>
<style scoped lang="scss">
.xy-table-item-label {
width: 180px;
}
::v-deep .el-input__inner {
text-align: left;
}
::v-deep .planTitle {
width: 300px;
display: flex;
background-color: #FFF;
background-image: none;
border-radius: 4px;
border: 1px solid #DCDFE6;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #606266;
display: inline-block;
font-size: inherit;
height: 40px;
line-height: 40px;
outline: 0;
padding: 0 15px;
}
.img__delete {
transform: scale(0.8, 0.8);
position: absolute;
top: 4px;
right: 4px;
}
::v-deep .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
::v-deep .avatar-uploader .el-upload:hover {
border-color: #338de3;
}
::v-deep .el-upload--picture-card {
font-size: 28px;
color: #8c939d;
width: 80px !important;
height: 80px !important;
line-height: 80px !important;
text-align: center;
}
::v-deep .avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 80px !important;
height: 80px !important;
line-height: 80px !important;
text-align: center;
}
::v-deep .avatar {
width: 80px !important;
display: block;
border-radius: 6px;
}
::v-deep .el-input__inner {
text-align: left;
}
</style>
Loading…
Cancel
Save