2025-10-09 09:54:13 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="detail-container">
|
|
|
|
|
<!-- 顶部导航 -->
|
|
|
|
|
<!-- <el-row class="navbar" type="flex" align="middle">
|
|
|
|
|
<el-col :span="2">
|
|
|
|
|
<el-button icon="el-icon-arrow-left" @click="goBack" circle></el-button>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="20" class="navbar-title">详情页</el-col>
|
|
|
|
|
</el-row> -->
|
|
|
|
|
|
|
|
|
|
<!-- 选项卡 -->
|
|
|
|
|
<el-tabs v-model="currentTab" @tab-click="switchTab">
|
|
|
|
|
<el-tab-pane
|
|
|
|
|
v-for="(item, index) in tapList"
|
|
|
|
|
:key="index"
|
|
|
|
|
:label="item.label"
|
|
|
|
|
:name="index.toString()"
|
|
|
|
|
></el-tab-pane>
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
|
|
|
|
<!-- 日期选择 -->
|
|
|
|
|
<el-date-picker
|
|
|
|
|
v-model="queryParams.dateRange"
|
|
|
|
|
type="daterange"
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
@change="loadData"
|
|
|
|
|
format="yyyy-MM-dd"
|
|
|
|
|
value-format="yyyy-MM-dd"
|
|
|
|
|
style="margin-bottom: 20px"
|
|
|
|
|
></el-date-picker>
|
|
|
|
|
|
|
|
|
|
<!-- 统计卡片 -->
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="6" v-for="(sKey, idx) in statsData" :key="idx">
|
|
|
|
|
<!-- 外层卡片点击 -->
|
|
|
|
|
<el-card
|
|
|
|
|
shadow="hover"
|
|
|
|
|
class="section-card"
|
|
|
|
|
@click.native="goList(sKey.selectType)"
|
|
|
|
|
>
|
|
|
|
|
<div slot="header" class="section-header">
|
|
|
|
|
<span class="section-tag">{{ sKey.name }}</span>
|
|
|
|
|
<span class="section-total">{{ sKey.total }} 台次</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="10" class="section-body">
|
|
|
|
|
<el-col :span="12" v-for="(item, i) in sKey.children" :key="i">
|
|
|
|
|
<!-- 内层点击绑定到 div 并阻止冒泡 -->
|
|
|
|
|
<div
|
|
|
|
|
class="kv"
|
|
|
|
|
@click.stop="goList(sKey.selectType, item.repairType)"
|
|
|
|
|
>
|
|
|
|
|
<div class="kv-number">{{ item.count }}</div>
|
|
|
|
|
<div class="kv-label">{{ dictData[item.repairType] }}</div>
|
|
|
|
|
<dict-tag :type="'repair_type'" :value="item.repairType" />
|
|
|
|
|
</div>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
<!-- 财务信息 -->
|
|
|
|
|
<div class="finance">
|
|
|
|
|
<el-card shadow="hover" class="fin-card receivable">
|
|
|
|
|
<div class="fin-top">
|
|
|
|
|
<span class="fin-title">应收款</span>
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
icon="el-icon-view"
|
|
|
|
|
@click.stop="toggleFinance('receivable')"
|
|
|
|
|
></el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-amount" @click="goListByPayStatus('receivable')">
|
|
|
|
|
{{
|
|
|
|
|
financeVisibility.receivable
|
|
|
|
|
? formatCurrency(otherInfo.receivableAmount || 0)
|
|
|
|
|
: "*****"
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-bottom" @click="goListByPayStatus('receivable')">
|
|
|
|
|
<span>{{ otherInfo.receivableCount }} 台次</span>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<el-card shadow="hover" class="fin-card collected">
|
|
|
|
|
<div class="fin-top">
|
|
|
|
|
<span class="fin-title">已收款</span>
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
icon="el-icon-view"
|
|
|
|
|
@click.stop="toggleFinance('collected')"
|
|
|
|
|
></el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-amount" @click="goListByPayStatus('receivedAmount')">
|
|
|
|
|
{{
|
|
|
|
|
financeVisibility.collected
|
|
|
|
|
? formatCurrency(otherInfo.receivedAmount)
|
|
|
|
|
: "*****"
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-bottom" @click="goListByPayStatus('receivedAmount')">
|
|
|
|
|
<span>{{ otherInfo.receivedCount }} 台次</span>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<el-card shadow="hover" class="fin-card pending">
|
|
|
|
|
<div class="fin-top">
|
|
|
|
|
<span class="fin-title">待收款</span>
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
icon="el-icon-view"
|
|
|
|
|
@click.stop="toggleFinance('pending')"
|
|
|
|
|
></el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-amount" @click="goListByPayStatus('pendingAmount')">
|
|
|
|
|
{{
|
|
|
|
|
financeVisibility.pending
|
|
|
|
|
? formatCurrency(otherInfo.pendingAmount)
|
|
|
|
|
: "*****"
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="fin-bottom" @click="goListByPayStatus('pendingAmount')">
|
|
|
|
|
<span>{{ otherInfo.pendingCount }} 台次</span>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
</div>
|
2025-11-13 16:07:47 +08:00
|
|
|
|
|
|
|
|
<!-- 工单列表弹窗 -->
|
|
|
|
|
<el-dialog
|
|
|
|
|
:title="dialogTitle"
|
|
|
|
|
:visible.sync="listDialogVisible"
|
|
|
|
|
width="80%"
|
|
|
|
|
v-if="listDialogVisible"
|
|
|
|
|
>
|
|
|
|
|
<TicketManagerItem
|
|
|
|
|
:is-type="dialogQueryParams.selectType"
|
|
|
|
|
:user-role="userRole"
|
|
|
|
|
:external-query-params="dialogQueryParams"
|
|
|
|
|
:show-view-only="true"
|
|
|
|
|
@close="listDialogVisible = false"
|
|
|
|
|
/>
|
|
|
|
|
</el-dialog>
|
2025-10-09 09:54:13 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import request from "@/utils/request";
|
|
|
|
|
import { formatCurrency, getDictByCode, getDateRange } from "@/utils/utils";
|
|
|
|
|
// import { checkPermi } from "@/utils/permission";
|
2025-11-13 16:07:47 +08:00
|
|
|
import TicketManagerItem from "@/views/repair/tickets/Components/TicketManagerItem.vue";
|
2025-10-09 09:54:13 +08:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: "DetailPagePC",
|
|
|
|
|
dicts: ["repair_type"],
|
2025-11-13 16:07:47 +08:00
|
|
|
components: {
|
|
|
|
|
TicketManagerItem
|
|
|
|
|
},
|
2025-10-09 09:54:13 +08:00
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
currentTab: "0",
|
|
|
|
|
queryParams: {
|
|
|
|
|
dateRange: [],
|
|
|
|
|
},
|
|
|
|
|
tapList: [
|
|
|
|
|
{ label: "本日", value: "day" },
|
|
|
|
|
{ label: "本月", value: "month" },
|
|
|
|
|
{ label: "全部", value: "all" },
|
|
|
|
|
],
|
|
|
|
|
statsData: [],
|
|
|
|
|
financeVisibility: {
|
|
|
|
|
receivable: false,
|
|
|
|
|
collected: false,
|
|
|
|
|
pending: false,
|
|
|
|
|
},
|
|
|
|
|
dictData: {},
|
|
|
|
|
otherInfo: {},
|
2025-11-13 16:07:47 +08:00
|
|
|
// 弹窗相关
|
|
|
|
|
listDialogVisible: false,
|
|
|
|
|
dialogTitle: "",
|
|
|
|
|
dialogQueryParams: {},
|
|
|
|
|
userRole: "all" // 默认角色,实际应用中可能需要动态获取
|
2025-10-09 09:54:13 +08:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
async mounted() {
|
|
|
|
|
this.queryParams.dateRange = getDateRange("day");
|
|
|
|
|
// this.loadFinanceVisibility();
|
|
|
|
|
this.loadData();
|
2025-11-13 16:07:47 +08:00
|
|
|
this.getDict();
|
2025-10-09 09:54:13 +08:00
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// checkPermi,
|
|
|
|
|
switchTab(tab) {
|
|
|
|
|
this.currentTab = tab.name;
|
|
|
|
|
const { value } = this.tapList[tab.name];
|
|
|
|
|
this.queryParams.dateRange = getDateRange(value);
|
|
|
|
|
this.loadData();
|
|
|
|
|
},
|
|
|
|
|
async getDict() {
|
|
|
|
|
const list = await getDictByCode("repair_type");
|
|
|
|
|
this.dictData =
|
|
|
|
|
list?.reduce((map, item) => {
|
|
|
|
|
map[item.value] = item.label;
|
|
|
|
|
return map;
|
|
|
|
|
}, {}) ?? {};
|
|
|
|
|
},
|
|
|
|
|
loadData() {
|
|
|
|
|
request({
|
|
|
|
|
url: "/repair/tickets/getBossNumStatistics",
|
|
|
|
|
method: "get",
|
|
|
|
|
params: this.queryParams,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.data) {
|
|
|
|
|
this.statsData = res.data.stats;
|
|
|
|
|
this.otherInfo = res.data;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
goList(selectType, repairType) {
|
|
|
|
|
console.log(selectType, repairType, 6666);
|
2025-11-13 16:07:47 +08:00
|
|
|
|
|
|
|
|
// 设置弹窗标题
|
|
|
|
|
this.dialogTitle = this.dictData[repairType] ?
|
|
|
|
|
`${this.dictData[repairType]}工单列表` :
|
|
|
|
|
`${this.getSelectTypeName(selectType)}工单列表`;
|
2025-10-09 09:54:13 +08:00
|
|
|
|
2025-11-13 16:07:47 +08:00
|
|
|
// 设置查询参数
|
|
|
|
|
this.dialogQueryParams = {
|
|
|
|
|
selectType: selectType,
|
|
|
|
|
repairType: repairType,
|
|
|
|
|
searchTimeArray: this.queryParams.dateRange
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 显示弹窗
|
|
|
|
|
this.listDialogVisible = true;
|
2025-10-09 09:54:13 +08:00
|
|
|
},
|
|
|
|
|
goListByPayStatus(payStatus) {
|
2025-11-13 16:07:47 +08:00
|
|
|
// 设置弹窗标题
|
|
|
|
|
this.dialogTitle = this.getPayStatusName(payStatus) + "工单列表";
|
|
|
|
|
|
|
|
|
|
// 设置查询参数
|
|
|
|
|
this.dialogQueryParams = {
|
|
|
|
|
payStatus: payStatus,
|
|
|
|
|
searchTimeArray: this.queryParams.dateRange
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 显示弹窗
|
|
|
|
|
this.listDialogVisible = true;
|
|
|
|
|
},
|
|
|
|
|
getSelectTypeName(selectType) {
|
|
|
|
|
const typeMap = {
|
|
|
|
|
'jinchang': '进厂',
|
|
|
|
|
'weixiuzhong': '维修中',
|
|
|
|
|
'yijungong': '已竣工',
|
|
|
|
|
'yijiaoche': '已交车',
|
|
|
|
|
'weijiesuan': '未结算',
|
|
|
|
|
'zaichang': '在厂'
|
|
|
|
|
};
|
|
|
|
|
return typeMap[selectType] || '工单';
|
|
|
|
|
},
|
|
|
|
|
getPayStatusName(payStatus) {
|
|
|
|
|
const statusMap = {
|
|
|
|
|
'receivable': '应收款',
|
|
|
|
|
'receivedAmount': '已收款',
|
|
|
|
|
'pendingAmount': '待收款'
|
|
|
|
|
};
|
|
|
|
|
return statusMap[payStatus] || '工单';
|
2025-10-09 09:54:13 +08:00
|
|
|
},
|
|
|
|
|
formatCurrency(amount) {
|
|
|
|
|
return formatCurrency(amount);
|
|
|
|
|
},
|
|
|
|
|
toggleFinance(key) {
|
|
|
|
|
this.financeVisibility[key] = !this.financeVisibility[key];
|
|
|
|
|
localStorage.setItem(
|
|
|
|
|
"financeVisibility",
|
|
|
|
|
JSON.stringify(this.financeVisibility)
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
loadFinanceVisibility() {
|
|
|
|
|
try {
|
|
|
|
|
const saved = JSON.parse(localStorage.getItem("financeVisibility"));
|
|
|
|
|
if (saved) this.financeVisibility = saved;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
goBack() {
|
|
|
|
|
this.$router.back();
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.detail-container {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
.navbar-title {
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
.section-card {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
.section-tag {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #2a6cff;
|
|
|
|
|
}
|
|
|
|
|
.section-total {
|
|
|
|
|
float: right;
|
|
|
|
|
}
|
|
|
|
|
.kv-number {
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
}
|
|
|
|
|
.kv-label {
|
|
|
|
|
color: #7f8fa4;
|
|
|
|
|
}
|
|
|
|
|
.finance {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
}
|
|
|
|
|
.fin-card {
|
|
|
|
|
flex: 1;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
.fin-title {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #7f8fa4;
|
|
|
|
|
}
|
|
|
|
|
.fin-amount {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
margin: 10px 0;
|
|
|
|
|
}
|
|
|
|
|
.fin-bottom {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #7f8fa4;
|
|
|
|
|
}
|
2025-11-13 16:07:47 +08:00
|
|
|
</style>
|