lanan-system-vue/src/views/repair/tickets/Components/TicketsShow.vue

787 lines
30 KiB
Vue
Raw Normal View History

2024-09-22 21:38:20 +08:00
<template>
<div class="app-container">
2025-09-10 11:00:50 +08:00
<el-dialog
title="单据详情"
:visible.sync="dialogVisible"
width="80%"
v-dialogDrag
append-to-body
>
2025-10-11 15:58:55 +08:00
<div v-loading="loading" element-loading-text="数据加载中..." style="min-height: 200px;">
<el-card class="box-card">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>工单信息</span>
</div>
<!-- 卡片内容 -->
<div>
<el-descriptions
class="margin-top"
:column="4"
:size="'medium'"
border
style="margin-bottom: 1rem"
>
<el-descriptions-item>
<template slot="label"> 订单编号 </template>
{{ info.ticketNo }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 维修类别 </template>
<dict-tag
:type="DICT_TYPE.REPAIR_TYPE"
v-model="info.repairType"
/>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 状态 </template>
<dict-tag
:type="DICT_TYPE.REPAIR_TICKETS_WORK_STATUS"
v-model="info.ticketsWorkStatus"
/>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 客户名称 </template>
{{ info.userName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 车牌号 </template>
{{ info.carNo }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 车系 </template>
{{ info.carBrandName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 手机号 </template>
{{ info.userMobile }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 经办人姓名 </template>
{{ info.handleName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 经办人电话 </template>
{{ info.handleMobile }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 创建时间 </template>
{{ parseTime(info.createTime, "{y}-{m}-{d}") }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 表显里程 </template>
{{ info.mileageTraveled }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 三包单位 </template>
{{ info.threePackUnits }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 保险名称 </template>
{{ info.insuranceName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 管理费 </template>
{{ info.managerMoney }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 救援费 </template>
{{ info.rescueMoney }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 三包费 </template>
{{ info.threePackMoney }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 定损费 </template>
{{ info.confirmFaultMoney }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 预计完工 </template>
{{ parseTime(info.outTime, "{y}-{m}-{d}") }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 合计金额 </template>
{{ info.totalPrice }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 最近保养日期 </template>
{{ parseTime(info.maintenanceDate, "{y}-{m}-{d}") }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 最近保养里程 </template>
{{ info.maintenanceMileage }}
</el-descriptions-item>
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 参考成本-->
<!-- </template>-->
<!-- {{ info.cost }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 参考毛利-->
<!-- </template>-->
<!-- {{ info.profit }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 领料状态-->
<!-- </template>-->
<!-- <dict-tag :type="DICT_TYPE.REPAIR_PART_STATUS" v-model="info.partStatus"/>-->
<!-- </el-descriptions-item>-->
<el-descriptions-item>
<template slot="label"> 服务顾问 </template>
{{ info.adviserName }}
</el-descriptions-item>
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 所属门店-->
<!-- </template>-->
<!-- {{ info.corpId }}-->
<!-- </el-descriptions-item>-->
<el-descriptions-item>
<template slot="label"> 工单状态 </template>
<dict-tag
:type="DICT_TYPE.REPAIR_TICKETS_STATUS"
v-model="info.ticketsStatus"
/>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 备注 </template>
{{ info.remark }}
</el-descriptions-item>
</el-descriptions>
</div>
</el-card>
<el-card class="box-card" v-if="projects && projects.length > 0">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>项目信息</span>
</div>
<!-- 卡片内容 -->
<div>
<TicketItemShow :list="projects" list-type="project" />
</div>
</el-card>
<el-card class="box-card" v-if="wares && wares.length > 0">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>材料信息</span>
<el-switch
v-if="userRole === 'service_advisor'"
style="float: right; padding: 3px 0"
v-model="info.partShow"
active-text="客户可见"
inactive-text="客户不可见"
active-value="1"
inactive-value="0"
@change="changeShow"
>
</el-switch>
</div>
<!-- 卡片内容 -->
<div>
<TicketItemShow :list="wares" list-type="ware" />
</div>
</el-card>
<el-card class="box-card" v-if="others && others.length > 0">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>附加信息</span>
</div>
<!-- 卡片内容 -->
<div>
<TicketItemShow :list="others" list-type="other" />
</div>
</el-card>
2025-10-11 15:58:55 +08:00
<el-card class="box-card">
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>合计</span>
</div>
<div>
<el-descriptions
class="margin-top"
:column="3"
:size="'medium'"
border
style="margin-bottom: 1rem"
>
<el-descriptions-item>
<template slot="label"> 总数量 </template>
{{ totalCount }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 成本 </template>
{{ otherInfo.cost }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 总金额 </template>
{{ totalMoney }}
</el-descriptions-item>
</el-descriptions>
</div>
<div v-hasPermi="['repair:tick:profit']">
<el-descriptions
class="margin-top"
:column="2"
:size="'medium'"
border
style="margin-bottom: 1rem"
>
<el-descriptions-item>
<template slot="label"> 含工时项目毛利率 </template>
{{ otherInfo.profitRate * 100 }}%
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 不含工时项目的毛利率 </template>
{{ otherInfo.profitRateNo * 100 }}%
</el-descriptions-item>
</el-descriptions>
</div>
</el-card>
2025-08-20 09:26:25 +08:00
2025-10-11 15:58:55 +08:00
<el-card class="box-card" v-hasPermi="['repair:tick:profit']">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus" />
<span>工种</span>
</div>
<!-- 卡片内容 -->
<div>
<TicketsJobType :list="otherInfo.groupByJobType" list-type="other" />
</div>
</el-card>
</div>
2024-09-22 21:38:20 +08:00
<div slot="footer" class="dialog-footer">
2025-10-11 15:58:55 +08:00
<div class="button-container">
<PrintButton
ref="printButton"
print-title="工单详情"
@click="handlePrint"
>
<template #printContent>
<div class="print-content">
<h1 style="text-align: center">工单详情</h1>
<h2>工单信息</h2>
2025-09-10 11:00:50 +08:00
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
2025-10-11 15:58:55 +08:00
<tbody>
2025-09-10 11:00:50 +08:00
<tr>
2025-10-11 15:58:55 +08:00
<td><strong>订单编号</strong></td>
<td>{{ info.ticketNo }}</td>
<td><strong>维修类别</strong></td>
<td>
{{ getDictDataLabel(DICT_TYPE.REPAIR_TYPE, info.repairType) }}
</td>
2025-09-10 11:00:50 +08:00
</tr>
2025-10-11 15:58:55 +08:00
<tr>
<td><strong>状态</strong></td>
2025-09-10 11:00:50 +08:00
<td>
{{
getDictDataLabel(
2025-10-11 15:58:55 +08:00
DICT_TYPE.REPAIR_TICKETS_WORK_STATUS,
info.ticketsWorkStatus
2025-09-10 11:00:50 +08:00
)
}}
</td>
2025-10-11 15:58:55 +08:00
<td><strong>客户名称</strong></td>
<td>{{ info.userName }}</td>
2025-09-10 11:00:50 +08:00
</tr>
<tr>
2025-10-11 15:58:55 +08:00
<td><strong>车牌号</strong></td>
<td>{{ info.carNo }}</td>
<td><strong>车系</strong></td>
<td>{{ info.carBrandName }}</td>
2025-09-10 11:00:50 +08:00
</tr>
2025-10-11 15:58:55 +08:00
<tr>
<td><strong>手机号</strong></td>
<td>{{ info.userMobile }}</td>
<td><strong>经办人姓名</strong></td>
<td>{{ info.handleName }}</td>
</tr>
<tr>
<td><strong>经办人电话</strong></td>
<td>{{ info.handleMobile }}</td>
<td><strong>创建时间</strong></td>
<td>{{ parseTime(info.createTime, "{y}-{m}-{d}") }}</td>
</tr>
<tr>
<td><strong>表显里程</strong></td>
<td>{{ info.mileageTraveled }}</td>
<td><strong>三包单位</strong></td>
<td>{{ info.threePackUnits }}</td>
</tr>
<tr>
<td><strong>保险名称</strong></td>
<td>{{ info.insuranceName }}</td>
<td><strong>管理费</strong></td>
<td>{{ info.managerMoney }}</td>
</tr>
<tr>
<td><strong>救援费</strong></td>
<td>{{ info.rescueMoney }}</td>
<td><strong>三包费</strong></td>
<td>{{ info.threePackMoney }}</td>
</tr>
<tr>
<td><strong>定损费</strong></td>
<td>{{ info.confirmFaultMoney }}</td>
<td><strong>预计完工</strong></td>
<td>{{ parseTime(info.outTime, "{y}-{m}-{d}") }}</td>
</tr>
<tr>
<td><strong>合计金额</strong></td>
<td>{{ info.totalPrice }}</td>
<td><strong>最近保养日期</strong></td>
2025-09-10 11:00:50 +08:00
<td>
2025-10-11 15:58:55 +08:00
{{ parseTime(info.maintenanceDate, "{y}-{m}-{d}") }}
2025-09-10 11:00:50 +08:00
</td>
</tr>
<tr>
2025-10-11 15:58:55 +08:00
<td><strong>最近保养里程</strong></td>
<td>{{ info.maintenanceMileage }}</td>
<td><strong>服务顾问</strong></td>
<td>{{ info.adviserName }}</td>
2025-09-10 11:00:50 +08:00
</tr>
2025-10-11 15:58:55 +08:00
<tr>
<td><strong>工单状态</strong></td>
2025-09-10 11:00:50 +08:00
<td>
{{
2025-10-11 15:58:55 +08:00
getDictDataLabel(
DICT_TYPE.REPAIR_TICKETS_STATUS,
info.ticketsStatus
)
2025-09-10 11:00:50 +08:00
}}
</td>
2025-10-11 15:58:55 +08:00
<td><strong>备注</strong></td>
<td>{{ info.remark }}</td>
2025-09-10 11:00:50 +08:00
</tr>
</tbody>
</table>
2025-10-11 15:58:55 +08:00
<div v-if="projects && projects.length > 0">
<h2>项目信息</h2>
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>规格</th>
<th>编码</th>
<th>单位</th>
<th>数量</th>
<th>单价</th>
<th>折扣</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利率</th>
<th>金额</th>
<th>施工人员</th>
<th>服务顾问</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in projects" :key="item.id">
<td>{{ index + 1 }}</td>
<td>{{ item.project?.name }}</td>
<td>{{ item.project?.model }}</td>
<td>{{ item.project?.code }}</td>
<td>
{{
getDictDataLabel(
DICT_TYPE.REPAIR_UNIT,
item.project?.unit
)
}}
</td>
<td>{{ item.itemCount }}</td>
<td>{{ item.itemPrice }}</td>
<td>{{ item.itemDiscount }}</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{ item.itemProfit }}
</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{
item.itemProfitRate
? (item.itemProfitRate * 100).toFixed(2) + "%"
: ""
}}
</td>
<td>{{ item.itemMoney }}</td>
<td>{{ item.repairNames }}</td>
<td>{{ item.saleName }}</td>
<td>{{ item.remark }}</td>
</tr>
</tbody>
</table>
</div>
<div v-if="wares && wares.length > 0">
<h2>材料信息</h2>
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>规格</th>
<th>编码</th>
<th>单位</th>
<th>数量</th>
<th>单价</th>
<th>折扣</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利率</th>
<th>金额</th>
<th>施工人员</th>
<th>服务顾问</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in wares" :key="item.id">
<td>{{ index + 1 }}</td>
<td>{{ item.ware?.name }}</td>
<td>{{ item.ware?.model }}</td>
<td>{{ item.ware?.code }}</td>
<td>
{{
getDictDataLabel(DICT_TYPE.REPAIR_UNIT, item.ware?.unit)
}}
</td>
<td>{{ item.itemCount }}</td>
<td>{{ item.itemPrice }}</td>
<td>{{ item.itemDiscount }}</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{ item.itemProfit }}
</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{
item.itemProfitRate
? (item.itemProfitRate * 100).toFixed(2) + "%"
: ""
}}
</td>
<td>{{ item.itemMoney }}</td>
<td>{{ item.repairNames }}</td>
<td>{{ item.saleName }}</td>
<td>{{ item.remark }}</td>
</tr>
</tbody>
</table>
</div>
<div v-if="others && others.length > 0">
<h2>附加信息</h2>
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>规格</th>
<th>编码</th>
<th>单位</th>
<th>数量</th>
<th>单价</th>
<th>折扣</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利</th>
<th v-if="checkPermi(['repair:tick:profit'])">毛利率</th>
<th>金额</th>
<th>施工人员</th>
<th>服务顾问</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in others" :key="item.id">
<td>{{ index + 1 }}</td>
<td>{{ item.other?.name }}</td>
<td>{{ item.other?.model }}</td>
<td>{{ item.other?.code }}</td>
<td>
{{
getDictDataLabel(DICT_TYPE.REPAIR_UNIT, item.other?.unit)
}}
</td>
<td>{{ item.itemCount }}</td>
<td>{{ item.itemPrice }}</td>
<td>{{ item.itemDiscount }}</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{ item.itemProfit }}
</td>
<td v-if="checkPermi(['repair:tick:profit'])">
{{
item.itemProfitRate
? (item.itemProfitRate * 100).toFixed(2) + "%"
: ""
}}
</td>
<td>{{ item.itemMoney }}</td>
<td>{{ item.repairNames }}</td>
<td>{{ item.saleName }}</td>
<td>{{ item.remark }}</td>
</tr>
</tbody>
</table>
</div>
<h2>合计</h2>
2025-09-10 11:00:50 +08:00
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
<tbody>
<tr>
2025-10-11 15:58:55 +08:00
<td><strong>总数量</strong></td>
<td>{{ totalCount }}</td>
<td><strong>成本</strong></td>
<td>{{ otherInfo.cost }}</td>
<td><strong>总金额</strong></td>
<td>{{ totalMoney }}</td>
2025-09-10 11:00:50 +08:00
</tr>
</tbody>
</table>
2025-10-11 15:58:55 +08:00
<div v-if="checkPermi(['repair:tick:profit'])">
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
>
<tbody>
<tr>
<td><strong>含工时项目毛利率</strong></td>
<td>{{ otherInfo.profitRate * 100 }}%</td>
<td><strong>不含工时项目的毛利率</strong></td>
<td>{{ otherInfo.profitRateNo * 100 }}%</td>
</tr>
</tbody>
</table>
<h2>工种</h2>
<table
class="print-table"
border="1"
cellspacing="0"
cellpadding="8"
style="
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
"
v-if="
otherInfo.groupByJobType &&
otherInfo.groupByJobType.length > 0
"
>
<thead>
<tr>
<th>工种</th>
<th>成本</th>
<th>售价</th>
<th>毛利</th>
<th>含工时毛利率</th>
<th>不含工时毛利率</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in otherInfo.groupByJobType"
:key="index"
>
<td>{{ item.jobTypeName }}</td>
<td>{{ item.cost }}</td>
<td>{{ item.money }}</td>
<td>{{ item.profit }}</td>
<td>{{ (item.profitRateWithWork * 100).toFixed(2) }}%</td>
<td>
{{ (item.profitRateWithoutWork * 100).toFixed(2) }}%
</td>
</tr>
</tbody>
</table>
</div>
2025-09-10 11:00:50 +08:00
</div>
2025-10-11 15:58:55 +08:00
</template>
</PrintButton>
2025-09-10 11:00:50 +08:00
2025-10-11 15:58:55 +08:00
<el-button @click="dialogVisible = false">关闭</el-button>
</div>
2024-09-22 21:38:20 +08:00
</div>
</el-dialog>
</div>
</template>
<script>
import TicketItemShow from "@/views/repair/tickets/Components/TicketItemShow.vue";
2025-09-10 11:00:50 +08:00
import { getTicketsById, updateShow } from "@/api/repair/tickets/Tickets";
2025-08-20 09:26:25 +08:00
import TicketsJobType from "@/views/repair/tickets/Components/TicketsJobType.vue";
2025-09-10 11:00:50 +08:00
import PrintButton from "@/components/PrintButton";
import { getDictDataLabel } from "@/utils/dict";
import { checkPermi } from "@/utils/permission";
2024-09-22 21:38:20 +08:00
export default {
name: "TicketsShow",
props: {
2025-09-10 11:00:50 +08:00
userRole: String,
2024-10-18 22:02:51 +08:00
},
2025-09-10 11:00:50 +08:00
components: { TicketsJobType, TicketItemShow, PrintButton },
2024-09-22 21:38:20 +08:00
data() {
return {
dialogVisible: false,
info: {},
projects: [],
wares: [],
others: [],
allList: [],
totalCount: 0,
2025-08-15 14:57:14 +08:00
totalMoney: 0,
2025-09-10 11:00:50 +08:00
otherInfo: {},
2025-10-11 15:58:55 +08:00
loading: false // 添加加载状态
2025-09-10 11:00:50 +08:00
};
2024-09-22 21:38:20 +08:00
},
methods: {
2025-09-10 11:00:50 +08:00
checkPermi,
2025-10-11 15:58:55 +08:00
// 添加打开弹窗的方法,支持加载动画
open(row) {
// 返回 Promise 以便调用者可以正确处理异步操作
return new Promise((resolve, reject) => {
this.reset();
this.loading = true; // 开启加载状态
getTicketsById(row.id).then(res => {
this.allList = res.data.items;
this.computed();
this.projects = this.allList.filter((item) => item.project);
this.wares = this.allList.filter((item) => item.ware);
this.others = this.allList.filter((item) => item.other);
this.info = row;
this.otherInfo = res.data;
this.dialogVisible = true;
this.loading = false; // 关闭加载状态
resolve();
}).catch((error) => {
this.loading = false; // 出错时也关闭加载状态
reject(error);
});
});
2024-10-18 22:02:51 +08:00
},
async changeShow() {
2024-10-18 22:02:51 +08:00
try {
2025-09-10 11:00:50 +08:00
await updateShow(this.info.id, this.info.partShow);
} catch {}
},
reset() {
2025-09-10 11:00:50 +08:00
this.info = {};
this.projects = [];
this.wares = [];
this.others = [];
this.allList = [];
},
2025-08-20 09:26:25 +08:00
computed() {
2025-09-10 11:00:50 +08:00
this.totalCount = 0;
this.totalMoney = 0;
2025-08-20 09:26:25 +08:00
if (this.allList && this.allList.length > 0) {
this.totalCount = this.allList.reduce((acc, cur) => {
2025-09-10 11:00:50 +08:00
return acc + cur.itemCount;
}, 0);
2025-08-20 09:26:25 +08:00
this.totalMoney = this.allList.reduce((acc, cur) => {
2025-09-10 11:00:50 +08:00
return acc + cur.itemMoney;
}, 0);
}
2025-09-10 11:00:50 +08:00
},
handlePrint() {
this.$refs.printButton.handlePrint();
},
getDictDataLabel,
},
};
2024-09-22 21:38:20 +08:00
</script>
<style scoped lang="scss">
.box-card {
margin-bottom: 10px;
}
2025-09-10 11:00:50 +08:00
.print-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 15px;
}
.print-table th,
.print-table td {
border: 1px solid #000;
padding: 8px 12px;
text-align: left;
}
.print-table th {
background-color: #f5f5f5;
font-weight: bold;
}
2025-10-11 15:58:55 +08:00
// 添加按钮容器样式,使按钮位于右下角
.dialog-footer {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 20px 0;
.button-container {
display: flex;
gap: 10px;
}
}
</style>