You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

648 lines
21 KiB

<template>
<div>
<div ref="contractList" style="padding: 0 20px">
<lx-header
icon="md-apps"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
text="出差管理"
>
<slot>
<div class="selects">
<div>
<span style="padding: 0 6px; word-break: keep-all">关键字</span>
<span>
<Input
v-model="select.keyword"
clearable
placeholder="关键字搜索"
style="width: 200px"
/>
</span>
</div>
<div>
<span>开始时间</span>
<span>
<DatePicker
:value="select.start_year"
placeholder="选择开始时间"
placement="bottom"
format="yyyy-MM-dd"
style="width: 120px"
@on-change="(e) => (select.start_year = $moment(e).format('YYYY-MM-DD'))"
></DatePicker>
</span>
</div>
<div>
<span>结束时间</span>
<span>
<DatePicker
:value="select.end_year"
placeholder="选择结束时间"
placement="bottom"
format="yyyy-MM-dd"
style="width: 120px"
@on-change="(e) => (select.end_year = $moment(e).format('YYYY-MM-DD'))"
></DatePicker>
</span>
</div>
<div>
<Button
type="primary"
@click="$router.push('/contract/away/addAway')">新增</Button>
</div>
<div>
<Button type="primary" @click="getList">查询</Button>
</div>
<div>
<Button
type="primary"
@click="goExpense()"
>出差报销
</Button>
</div>
</div>
</slot>
</lx-header>
<xy-table
ref="xyTable"
:list="list"
:table-item="table"
@editor=""
>
<template v-slot:btns>
<el-table-column
fixed="right"
header-align="center"
label="操作"
width="220"
>
<template #default="{ row }" v-if="!/Finance/g.test($route.path)">
<Button style="margin: 2px;" size="small" type="primary" @click="printFlow(row)">打印流程</Button>
<template v-if="row.away_status === 1 && row.expense_status === 1">
<Poptip
v-if="isAuthEdit(row)"
:transfer="true"
confirm
placement="bottom"
title="确认要删除吗"
@on-ok="() => deleteAway(row.id)"
>
<Button
style="margin: 2px;"
ghost
size="small"
type="error"
>删除
</Button>
</Poptip>
<Button
style="margin: 2px;"
size="small"
type="primary"
@click="$refs['addAway'].setType('editor'),$refs['addAway'].setId(row.id),$refs['addAway'].show()"
>编辑
</Button>
</template>
<template v-if="row.FLOWSTATUS.useCar.isEnabled()">
<Button
style="margin: 2px;"
size="small"
type="primary"
@click="goUseCar(row)"
>用车审核
</Button>
</template>
<template v-if="row.FLOWSTATUS.subsidize.isEnabled()">
<Button
style="margin: 2px;"
size="small"
type="primary"
@click="goSubsidize(row)"
>市内补助审核
</Button>
</template>
<template v-if="row.FLOWSTATUS.away.isEnabled()">
<Button
style="margin: 2px;"
size="small"
type="primary"
@click="goAway(row)"
>出差审核
</Button>
</template>
<template v-if="row.FLOWSTATUS.expense.isEnabled()">
<Button
style="margin: 2px;"
size="small"
type="primary"
@click="goExpense(row)"
>出差报销
</Button>
</template>
</template>
<template v-else #default="{ row }">
<template v-if="row.FLOWSTATUS.expense.getStatus() === 3">
<Button
v-if="row.FLOWSTATUS.financial.getStatus() !== 2"
style="margin: 2px;"
size="small"
type="primary"
@click="$refs['examineAway'].getContract(row);$refs['examineAway'].isShowPaymentRegistration=true;"
ghost
>审核确认
</Button>
</template>
<template v-if="/Finance/g.test($route.path)">
<Button
v-if="isAuthCanExpense(row)"
style="margin: 2px;"
size="small"
type="primary"
@click="canExpense(row,1)"
>开启报销
</Button>
<Button
v-else
style="margin: 2px;"
size="small"
type="primary"
ghost
@click="canExpense(row,0)"
>关闭报销
</Button>
</template>
</template>
</el-table-column>
</template>
</xy-table>
<div style="display: flex; justify-content: flex-end;padding: 10px 6px;">
<Page
:total="total"
show-elevator
@on-change="e => {
select.page = e;
getList();
}"
show-sizer
@on-page-size-change="e => {
select.page = 1;
select.page_size = e;
getList();
}"
/>
</div>
</div>
<addAway ref="addAway" @refresh="getList"></addAway>
<examineAway ref="examineAway" @refresh="getList"></examineAway>
</div>
</template>
<script>
import examineAway from "@/views/away/component/examineAway.vue";
import addAway from "@/views/away/component/addAway.vue"
import { index, destroy, save } from "@/api/away";
import {getToken} from "@/utils/auth";
export default {
components: {
addAway,
examineAway
},
data() {
return {
expenseUser: ["admin","panjiajia","huyangcui","wanghui"],
window: {
width: 0,
height: 0,
top: 0,
left: 0,
},
select: {
keyword: '',
start_year: "",
end_year: "",
page: 1,
page_size: 10
},
total: 0,
list: [],
flowStatus: new Map([
[0, "-"],
[1, "待申请"],
[2, "流转中"],
[3, "已办结"]
]),
flowStatusColor: new Map([
[0, "rgb(140, 140, 140)"],
[1, "rgb(96, 109, 241)"],
[2, "rgb(219, 122, 122)"],
[3, "rgb(147, 201, 134)"]
]),
table: [
{
type: 'selection',
width: 54,
reserveSelection: true,
selectable: row => row.away_flow_id && row.away_status === 3 && !row.expense_flow_id,
fixed: "left"
},
{
label: "出差事由",
prop: "title",
width: 200,
align: "left",
fixed: "left"
},
{
label: "开始时间",
prop: "start_date",
width: 120
},
{
label: "结束时间",
prop: "end_date",
width: 120
},
{
label: "是否用车",
prop: "use_car",
formatter: (cell, data, value) => {
return value? "是" : "否";
},
},
{
label: "是否市内补助",
prop: "is_subsidize",
formatter: (cell, data, value) => {
return value? "是" : "否";
},
width: 140
},
{
label: "流程状态",
multiHd: [
// {
// width: 100,
// label: "用车",
// customFn:row => {
// if (!row.use_car) {
// return (
// <span style="color: rgb(140, 140, 140);">-</span>
// )
// }
// return (
// <div>
// <span style={{ 'color': this.flowStatusColor.get(row.FLOWSTATUS.useCar.getStatus()) }}>{ this.flowStatus.get(row.FLOWSTATUS.useCar.getStatus()) || '待申请' }</span>
// <br/>
// {
// (row.FLOWSTATUS.useCar.getStatus() > 1) ? <a style="color: #333" on={{['click']:()=>{
// this.toOaDetail('useCar',row,)
// }}}>查看</a> : ''
// }
// </div>
// )
// }
// },
// {
// width: 100,
// label: "市内补助",
// customFn:row => {
// if (!row.is_subsidize) {
// return (
// <span style="color: rgb(140, 140, 140);">-</span>
// )
// }
// return (
// <div>
// <span style={{ 'color': this.flowStatusColor.get(row.FLOWSTATUS.subsidize.getStatus()) }}>{ this.flowStatus.get(row.FLOWSTATUS.subsidize.getStatus()) || '待申请' }</span>
// <br/>
// {
// (row.FLOWSTATUS.subsidize.getStatus() > 1) ? <a style="color: #333" on={{['click']:()=>{
// this.toOaDetail('subsidize',row)
// }}}>查看</a> : ''
// }
// </div>
// )
// }
//
// },
{
width: 100,
label: "出差审批",
customFn:row => {
return (
<div>
<span style={{ 'color': this.flowStatusColor.get(row.FLOWSTATUS.away.getStatus()) }}>{ this.flowStatus.get(row.FLOWSTATUS.away.getStatus()) || '待申请' }</span>
<br/>
{
(row.FLOWSTATUS.away.getStatus() > 1) ? <a style="color: #333" on={{['click']:()=>{
this.toOaDetail('away',row)
}}}>查看</a> : ''
}
</div>
)
}
},
{
label: "出差报销",
width: 100,
customFn:row => {
return (
<div>
{
((this.$moment().diff(this.$moment(row.end_date),"days") <= 30) || (row.FLOWSTATUS.expense.getStatus() > 1)) ?
(<span style={{ 'color': this.flowStatusColor.get(row.FLOWSTATUS.expense.getStatus()) }}>{ this.flowStatus.get(row.FLOWSTATUS.expense.getStatus()) || '待申请' }</span>) :
(<span style="color: red">超时未办理</span>)
}
<br/>
{
(row.FLOWSTATUS.expense.getStatus() > 1) ? <a style="color: #333" on={{['click']:()=>{
this.toOaDetail('expense',row)
}}}>查看</a> : ''
}
</div>
)
}
},
{
width: 100,
label: "财务审核",
customFn:row => {
return (row.FLOWSTATUS.financial.getStatus() === 2) ?
(<span style="color: green;">已确认</span>) :
(<span style="color: #666;">待审核</span>)
}
}
]
},
{
label: "创建日期",
width: 160,
prop: "created_at",
formatter: (cell, data, value) => {
return this.$moment(value).format("YYYY-MM-DD HH:mm");
},
},
{
label: "业务科室",
width: 140,
prop: "department.name",
},
{
label: "经办人",
width: 140,
prop: "admin.name",
},
]
}
},
methods: {
printFlow (row) {
let id;
if (row.away_flow_id) {
id = row.away_flow_id;
} else if (row.expense_flow_id) {
id = row.expense_flow_id
} else {}
if (!id) {
this.$message.warning("未找到流程");
return
}
window.open(`${process.env.VUE_APP_OUT_URL}/flow/print-relate-flow?id=${id}&except_self=0&auth_token=${this.$store.getters.oa_token}`,"_blank")
},
async toOaDetail (tbname,row) {
let url = `${process.env.VUE_APP_OUT_URL}/#/flow/detail?auth_token=${window.encodeURIComponent(getToken())}&isSinglePage=1&flow_id=`
switch (tbname) {
case "away":
url += row.away_flow_id
break;
case 'expense':
url += row.expense_flow_id
break;
default:
url = `${process.env.VUE_APP_OUT_URL}/flow/list/todo`
}
this.oaUrl = url
this.isShowOaModal = true
},
goUseCar (row) {
const baseInfo = {
"flow_title": row.title,
"65802fc31dc8f": row.start_date,
"65f7e6e45ab4f": row.end_date,
"657be2e1bbda8": row.title
};
let url = `${process.env.VUE_APP_OUT_OLD}/flow/create/3?auth_token=${this.$store.getters.oa_token}&out_away_id=${
row.id
}&default_json=${JSON.stringify(baseInfo)}`;
window.open(
url,
"buyProcess",
`top=${this.window.top},left=${this.window.left},width=${this.window.width},height=${this.window.height},location=0`
);
},
goSubsidize (row) {
const baseInfo = {
"flow_title": row.title,
"6584041d45cd9": row.title
};
let url = `${process.env.VUE_APP_OUT_OLD}/flow/create/24?auth_token=${this.$store.getters.oa_token}&out_away_id=${
row.id
}&default_json=${JSON.stringify(baseInfo)}`;
window.open(
url,
"buyProcess",
`top=${this.window.top},left=${this.window.left},width=${this.window.width},height=${this.window.height},location=0`
);
},
goAway (row) {
// 70
const baseInfo = {
"flow_title": row.title,
"kaishi": row.start_date,
"jieshu": row.end_date,
"chuchaishiyou": row.title,
};
let url = `${process.env.VUE_APP_OUT_OLD}/#/flow/create?auth_token=${window.encodeURIComponent(getToken())}&module_name=oa&isSinglePage=1&module_id=70&out_away_id=${row.id}&default_json=${JSON.stringify(baseInfo)}`;
console.log('url',url)
this.oaUrl = url
this.isShowOaModal = true
},
goExpense (row) {
let url;
if (row) {
const baseInfo = {
"flow_title": row.title,
"totalAmt": row.expense,
"chuchaishiyou": row.title,
"65af398d89e75": row.away_flow_id,
};
url = `${process.env.VUE_APP_OUT_OLD}/#/flow/create?auth_token=${window.encodeURIComponent(getToken())}&module_name=oa&isSinglePage=1&module_id=78&out_away_id=${row.id}&default_json=${JSON.stringify(baseInfo)}`;
} else {
let rows = this.$refs['xyTable'].getSelection()
const baseInfo = {
"flow_title": rows.map(row => row.title).toString() ,
"totalAmt": row.reduce((pre, cur) => pre + Number(row.expense??0),0),
"chuchaishiyou": rows.map(row => row.title).toString(),
"65af398d89e75": rows.map(row => row.away_flow_id).toString(),
};
url = `${process.env.VUE_APP_OUT_OLD}/#/flow/create?auth_token=${window.encodeURIComponent(getToken())}&module_name=oa&isSinglePage=1&module_id=78&out_away_id=${rows.map(i => i.id)?.toString()}&default_json=${JSON.stringify(baseInfo)}`;
}
console.log('url',url)
this.oaUrl = url
this.isShowOaModal = true
},
async getList (isFirst) {
class Flow {
status = 0
executable = false
constructor(status=0, executable=false) {
this.status = status
this.executable = executable
}
setStatus (status) {
this.status = status
}
setExecutable (executable) {
if (typeof executable === 'boolean') {
this.executable = executable
}
}
getStatus () {
return this.status
}
getExecutable () {
return this.executable
}
isEnabled () {
return this.executable && this.status === 1
}
}
const res = await index(this.select,!isFirst);
delete this.select.id;
this.total = res.total;
this.list = res.data;
this.list.forEach(item => {
let flowStatus = {
"useCar": new Flow(),
"subsidize": new Flow(),
"away": new Flow(),
"expense": new Flow(),
"financial": new Flow()
}
// if (item.use_car) {
// flowStatus.useCar.setStatus(item.use_car_status)
// if (item.use_car_status === 1) {
// flowStatus.useCar.setExecutable(true)
// }
// }
// if (item.is_subsidize) {
// flowStatus.subsidize.setStatus(item.subsidize_status)
// if (item.subsidize_status === 1) {
// flowStatus.subsidize.setExecutable(true)
// }
// }
flowStatus.away.setStatus(item.away_status)
if (item.away_status === 1) {
flowStatus.away.setExecutable(true)
}
flowStatus.expense.setStatus(item.expense_status)
// if ((!item.is_subsidize || item.subsidize_status === 3) && (!item.use_car || item.use_car_status === 3) && item.away_status === 3 && (!item.expense_status || item.expense_status === 1) && (this.$moment().diff(this.$moment(item.end_date),"days") <= 30 || item.can_expenses)) {
// flowStatus.expense.setExecutable(true)
// }
if (item.away_status === 3 && (!item.expense_status || item.expense_status === 1) && (this.$moment().diff(this.$moment(item.end_date),"days") <= 30 || item.can_expenses)) {
flowStatus.expense.setExecutable(true)
}
flowStatus.financial.setStatus(item.financial_status)
if (item.expense_status === 3) {
flowStatus.financial.setExecutable(true)
}
item.FLOWSTATUS = flowStatus;
});
},
async deleteAway (id) {
await destrxoy({ id });
await this.getList();
},
examineAway (row, status) {
this.$confirm("是否确认审批?", "提示", {}).then(_ => {
save({
...row,
financial_status: status
}).then(_ => {
this.$message.success("操作成功");
this.getList()
})
})
},
canExpense (row, status) {
this.$confirm(`是否${ status ? "开启" : "关闭" }报销?`, "提示", {}).then(_ => {
save({
...row,
can_expenses: status
}).then(_ => {
this.$message.success("操作成功");
this.getList()
})
})
},
},
computed: {
isAuthEdit () {
return function (row) {
return !(row.FLOWSTATUS.useCar.getStatus() > 1 || row.FLOWSTATUS.subsidize.getStatus() > 1 || row.FLOWSTATUS.away.getStatus() > 1 || row.FLOWSTATUS.financial.getStatus() > 1)
}
},
isAuthCanExpense () {
return function (row) {
return (this.$moment().diff(this.$moment(row.end_date),"days") > 30) && this.expenseUser.indexOf(this.$store.state.user.username) !== -1 && !row.can_expenses
}
}
},
created() {
this.window.width = screen.availWidth * 0.95;
this.window.height = screen.availHeight * 0.95;
this.window.top = (window.screen.height - 30 - this.window.height) / 2;
this.window.left = (window.screen.width - 10 - this.window.width) / 2;
this.select.id = this.$route.query.awayId;
this.getList(true)
window.onfocus = () => {
this.getList()
}
},
destroyed() {
window.onfocus = null;
}
}
</script>
<style scoped lang="scss">
.selects {
display: flex;
flex-wrap: wrap;
& > div {
margin-bottom: 6px;
margin-right: 4px;
& > span {
word-break: keep-all;
padding: 0 4px ;
}
}
}
</style>