基本配置修改 优化
This commit is contained in:
parent
b0c2b0cd3b
commit
a9f150c446
|
|
@ -0,0 +1,45 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询食堂支付记录列表
|
||||
export function listCanteenRecord(query) {
|
||||
return request({
|
||||
url: '/smart-canteen/api/v2/report/consume/list',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//人员报表信息查询
|
||||
export function peoplelistRecord(query) {
|
||||
return request({
|
||||
url: '/smart-canteen/api/v2/report/consume/peoplelist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//获取组织树
|
||||
export function getTree(query) {
|
||||
return request({
|
||||
url: '/smart-canteen/api/v2/report/tree',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询详情列表
|
||||
export function getDetailList(query) {
|
||||
return request({
|
||||
url: '/smart-canteen/api/v2/report/consume/listByArea',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
||||
// 若依内置了 download 工具,页面里直接用 this.download 更方便(见下)
|
||||
export function download(query) {
|
||||
return request({
|
||||
url: '/smart-canteen/api/v2/report/consume/exportExcel',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询条件 -->
|
||||
<el-form :inline="true" :model="queryParams" class="demo-form-inline" style="display: flex; align-items: center; flex-wrap: wrap;">
|
||||
<el-form-item label="支付开始时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.startPayTime"
|
||||
type="datetime"
|
||||
placeholder="选择开始时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付结束时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.endPayTime"
|
||||
type="datetime"
|
||||
placeholder="选择结束时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
clearable
|
||||
/>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button type="success" @click="exportExcel" style="margin-left: 8px;">导出</el-button>
|
||||
</el-form-item>
|
||||
<!-- 查询按钮和合计在同一行 -->
|
||||
<el-form-item style="margin-left: auto;">
|
||||
<div style="display: inline-block; margin-left: 20px; font-size: 20px; color: #606266;">
|
||||
合计:<b style="color: #67C23A;">{{ pageTotals.total.toFixed(2) }}</b> 元
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 主表格 -->
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
style="width: 100%"
|
||||
:header-cell-style="tableHeaderStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
v-loading="loading"
|
||||
element-loading-text="数据加载中..."
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(255, 255, 255, 0.8)"
|
||||
>
|
||||
<el-table-column label="食堂名称" prop="orgName" align="center" />
|
||||
<el-table-column label="预订餐消费" prop="reserveAmount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row,1)">
|
||||
{{ Math.abs(scope.row.reserveAmount) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="食堂消费" prop="canteenAmount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row,3)">
|
||||
{{ Math.abs(scope.row.canteenAmount) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="超市消费" prop="superAmount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row,4)">
|
||||
{{ Math.abs(scope.row.superAmount) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="驿站消费" prop="h5Amount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row,2)">
|
||||
{{ Math.abs(scope.row.h5Amount) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消费补扣" prop="deductionAmount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row,5)">
|
||||
{{ Math.abs(scope.row.deductionAmount) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总和" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span
|
||||
style="color: #67c23a; font-weight: bold;"
|
||||
>
|
||||
{{
|
||||
(
|
||||
Math.abs(scope.row.reserveAmount || 0) +
|
||||
Math.abs(scope.row.canteenAmount || 0) +
|
||||
Math.abs(scope.row.superAmount || 0) +
|
||||
Math.abs(scope.row.deductionAmount || 0) +
|
||||
Math.abs(scope.row.h5Amount || 0)
|
||||
).toFixed(2)
|
||||
}}
|
||||
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<!-- 主表分页 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<el-dialog
|
||||
:visible.sync="detailVisible"
|
||||
:title="detail.orgName + ' - 消费详情'"
|
||||
width="1400px"
|
||||
class="detail-dialog"
|
||||
>
|
||||
<!-- 导出按钮 -->
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
style="margin-bottom: 10px;"
|
||||
@click="exportDetailExcel"
|
||||
>
|
||||
导出详情
|
||||
</el-button>
|
||||
<!-- 消费金额展示 -->
|
||||
<div style="margin-bottom: 10px; font-weight: bold; font-size: 16px;">
|
||||
当前{{ detailType }}消费金额:<span style="color: #409eff;">{{ Math.abs(detailAmount) }}</span> 元
|
||||
</div>
|
||||
<el-table
|
||||
:data="detailData"
|
||||
border
|
||||
style="width: 100%"
|
||||
height="600px"
|
||||
:header-cell-style="tableHeaderStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
>
|
||||
<el-table-column
|
||||
label="序号"
|
||||
align="center"
|
||||
type="index"
|
||||
:index="indexMethod"
|
||||
width="80"
|
||||
/>
|
||||
<el-table-column label="所属组织" prop="orgFullName" align="center" />
|
||||
<el-table-column label="人员姓名" prop="custName" align="center" />
|
||||
<el-table-column label="消费金额" prop="amount" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.amount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消费类型" prop="canteenAmount" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="clickable" @click="handleDetail(scope.row)">
|
||||
<span :style="{ color: getConsumeTypeColor(scope.row) }">
|
||||
{{ getConsumeTypeLabel(scope.row) }}
|
||||
</span>
|
||||
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付时间" prop="payTime" align="center" />
|
||||
</el-table>
|
||||
<!-- 详情分页 -->
|
||||
<pagination
|
||||
v-show="detailTotal > 0"
|
||||
:total="detailTotal"
|
||||
:page.sync="detailParams.pageNum"
|
||||
:limit.sync="detailParams.pageSize"
|
||||
@pagination="getDetailList"
|
||||
/>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">关闭</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCanteenRecord, getDetailList } from "@/api/canteen/canteenRecord";
|
||||
import ExcelJS from "exceljs";
|
||||
import { saveAs } from "file-saver";
|
||||
export default {
|
||||
name: "CanteenRecord",
|
||||
data() {
|
||||
const today = new Date();
|
||||
const startOfDay = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(
|
||||
today.getDate()
|
||||
).padStart(2, "0")} 00:00:00`;
|
||||
const endOfDay = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(
|
||||
today.getDate()
|
||||
).padStart(2, "0")} 23:59:59`;
|
||||
return {
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
startPayTime: startOfDay,
|
||||
endPayTime: endOfDay,
|
||||
orgId: null,
|
||||
},
|
||||
detailType: "",
|
||||
detailAmount: "",
|
||||
loading: false,
|
||||
detailAmount: 0, // 当前点击行的消费金额
|
||||
total: 0,
|
||||
tableData: [],
|
||||
detailVisible: false,
|
||||
detail: {},
|
||||
detailData: [],
|
||||
detailTotal: 0,
|
||||
detailParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
computed: {
|
||||
pageTotals() {
|
||||
const totals = { reserve: 0, canteen: 0, super: 0, h5: 0, deduction: 0, total: 0 };
|
||||
(this.tableData || []).forEach(row => {
|
||||
const reserve = Math.abs(Number(row.reserveAmount) || 0);
|
||||
const canteen = Math.abs(Number(row.canteenAmount) || 0);
|
||||
const sup = Math.abs(Number(row.superAmount) || 0);
|
||||
const h5 = Math.abs(Number(row.h5Amount) || 0);
|
||||
const deduction = Math.abs(Number(row.deductionAmount) || 0);
|
||||
|
||||
totals.reserve += reserve;
|
||||
totals.canteen += canteen;
|
||||
totals.super += sup;
|
||||
totals.h5 += h5;
|
||||
totals.deduction += deduction;
|
||||
});
|
||||
totals.total = totals.reserve + totals.canteen + totals.super + totals.h5 + totals.deduction;
|
||||
return totals;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportExcel() {
|
||||
if (!this.tableData || this.tableData.length === 0) {
|
||||
this.$message.warning("暂无数据可导出");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建工作簿和表
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet("消费统计");
|
||||
|
||||
// 表头
|
||||
const header = ["食堂名称", "预订餐消费", "食堂消费", "超市消费", "驿站消费","消费补扣","总和"];
|
||||
sheet.addRow(header);
|
||||
|
||||
// 数据行
|
||||
this.tableData.forEach(item => {
|
||||
sheet.addRow([
|
||||
item.orgName,
|
||||
Math.abs(item.reserveAmount || 0),
|
||||
Math.abs(item.canteenAmount || 0),
|
||||
Math.abs(item.superAmount || 0),
|
||||
Math.abs(item.h5Amount || 0),
|
||||
Math.abs(item.deductionAmount || 0),
|
||||
(
|
||||
Math.abs(item.reserveAmount || 0) +
|
||||
Math.abs(item.canteenAmount || 0) +
|
||||
Math.abs(item.superAmount || 0) +
|
||||
Math.abs(item.deductionAmount || 0) +
|
||||
Math.abs(item.h5Amount || 0)
|
||||
).toFixed(2)
|
||||
]);
|
||||
});
|
||||
|
||||
// 设置列宽 + 居中
|
||||
sheet.columns = [
|
||||
{ header: "所属组织", key: "orgFullName", width: 40 },
|
||||
{ header: "人员姓名", key: "custName", width: 10 },
|
||||
{ header: "消费金额", key: "amount", width: 10 },
|
||||
{ header: "消费类型", key: "flow_type_name", width: 10 },
|
||||
{ header: "支付时间", key: "payTime", width: 30 },
|
||||
];
|
||||
|
||||
|
||||
// 表头样式
|
||||
sheet.getRow(1).eachCell(cell => {
|
||||
cell.font = { bold: true, size: 12, color: { argb: "FF000000" } };
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
cell.fill = {
|
||||
type: "pattern",
|
||||
pattern: "solid",
|
||||
fgColor: { argb: "FFEAEAEA" } // 灰色底
|
||||
};
|
||||
cell.border = {
|
||||
top: { style: "thin" },
|
||||
left: { style: "thin" },
|
||||
bottom: { style: "thin" },
|
||||
right: { style: "thin" }
|
||||
};
|
||||
});
|
||||
|
||||
// 数据行样式(居中 + 边框)
|
||||
sheet.eachRow((row, rowNumber) => {
|
||||
if (rowNumber !== 1) {
|
||||
row.eachCell(cell => {
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
cell.border = {
|
||||
top: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
left: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
bottom: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
right: { style: "thin", color: { argb: "FFCCCCCC" } }
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 导出文件
|
||||
workbook.xlsx.writeBuffer().then(buffer => {
|
||||
const fileName = `消费统计_${new Date().toLocaleDateString().replace(/\//g, "-")}.xlsx`;
|
||||
saveAs(new Blob([buffer], { type: "application/octet-stream" }), fileName);
|
||||
});
|
||||
},
|
||||
|
||||
/** 导出详情表格 */
|
||||
exportDetailExcel() {
|
||||
if (!this.detailData || this.detailData.length === 0) {
|
||||
this.$message.warning("暂无详情数据可导出");
|
||||
return;
|
||||
}
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet("消费详情");
|
||||
|
||||
// 表头
|
||||
const header = ["所属组织", "人员姓名", "消费金额", "消费类型", "支付时间"];
|
||||
sheet.addRow(header);
|
||||
|
||||
// 数据行
|
||||
this.detailData.forEach(item => {
|
||||
// 消费类型处理
|
||||
let flowTypeLabel = item.flow_type_name || "";
|
||||
if (!flowTypeLabel) {
|
||||
const ft = Number(item.flowType ?? item.flow_type);
|
||||
if (ft === 110) flowTypeLabel = "消费";
|
||||
else if (ft === 130) flowTypeLabel = "退款";
|
||||
else if (ft === 120) flowTypeLabel = "补扣";
|
||||
else flowTypeLabel = "其他";
|
||||
}
|
||||
// 简单处理金额负数
|
||||
const ft = Number(item.flowType ?? item.flow_type);
|
||||
if (ft === 110 || ft === 120) {
|
||||
item.amount = -Math.abs(item.amount); // 消费和补扣为负
|
||||
} else if (ft === 130) {
|
||||
item.amount = Math.abs(item.amount); // 退款为正
|
||||
}
|
||||
sheet.addRow([
|
||||
item.orgFullName || "",
|
||||
item.custName || "",
|
||||
item.amount,
|
||||
flowTypeLabel,
|
||||
item.payTime || ""
|
||||
]);
|
||||
});
|
||||
|
||||
// 设置列宽 + 居中
|
||||
sheet.columns.forEach(col => {
|
||||
col.width = 18;
|
||||
col.alignment = { vertical: "middle", horizontal: "center" };
|
||||
});
|
||||
|
||||
// 表头样式
|
||||
sheet.getRow(1).eachCell(cell => {
|
||||
cell.font = { bold: true, size: 12, color: { argb: "FF000000" } };
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
cell.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FFEAEAEA" } };
|
||||
cell.border = {
|
||||
top: { style: "thin" },
|
||||
left: { style: "thin" },
|
||||
bottom: { style: "thin" },
|
||||
right: { style: "thin" }
|
||||
};
|
||||
});
|
||||
|
||||
// 数据行样式(居中 + 边框)
|
||||
sheet.eachRow((row, rowNumber) => {
|
||||
if (rowNumber !== 1) {
|
||||
row.eachCell(cell => {
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
cell.border = {
|
||||
top: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
left: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
bottom: { style: "thin", color: { argb: "FFCCCCCC" } },
|
||||
right: { style: "thin", color: { argb: "FFCCCCCC" } }
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 导出文件
|
||||
workbook.xlsx.writeBuffer().then(buffer => {
|
||||
const fileName = `消费详情_${this.detail.orgName}_${new Date().toLocaleDateString().replace(/\//g, "-")}.xlsx`;
|
||||
saveAs(new Blob([buffer], { type: "application/octet-stream" }), fileName);
|
||||
});
|
||||
},
|
||||
getConsumeTypeLabel(row) {
|
||||
if(row.flowType ==110){
|
||||
return '消费'
|
||||
}else if(row.flowType == 130){
|
||||
return '退款'
|
||||
}else if(row.flowType ==120){
|
||||
return '补扣'
|
||||
}
|
||||
},
|
||||
getConsumeTypeColor(row,type) {
|
||||
let amount = Number(row.amount || 0)
|
||||
return amount >= 0 ? 'green' : 'red'
|
||||
},
|
||||
tableHeaderStyle() {
|
||||
return { background: "#f5f7fa", fontWeight: "bold", textAlign: "center" };
|
||||
},
|
||||
tableCellStyle() {
|
||||
return { textAlign: "center" };
|
||||
},
|
||||
/** 查询主表 */
|
||||
getList() {
|
||||
this.loading = true; // 开启加载
|
||||
listCanteenRecord(this.queryParams).then((res) => {
|
||||
this.tableData = res|| [];
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleQuery() {
|
||||
if (
|
||||
this.queryParams.startPayTime &&
|
||||
this.queryParams.endPayTime &&
|
||||
this.queryParams.endPayTime < this.queryParams.startPayTime
|
||||
) {
|
||||
this.$message.error("结束时间不能早于开始时间");
|
||||
return;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = { pageNum: 1, pageSize: 10, startPayTime: null, endPayTime: null, orgId: null };
|
||||
this.getList();
|
||||
},
|
||||
/** 查看详情 */
|
||||
handleDetail(row,status) {
|
||||
this.detail = row;
|
||||
this.detailAmount = this.getAmountByStatus(row, status); // 取对应消费金额
|
||||
this.detailParams.pageNum = 1;
|
||||
this.detailVisible = true;
|
||||
if (status === 1) {
|
||||
this.detailType = "预订餐";
|
||||
this.detailAmount = row.reserveAmount;
|
||||
} else if (status === 3) {
|
||||
this.detailType = "食堂";
|
||||
this.detailAmount = row.canteenAmount;
|
||||
} else if (status === 4) {
|
||||
this.detailType = "超市";
|
||||
this.detailAmount = row.superAmount;
|
||||
} else if (status === 2) {
|
||||
this.detailType = "驿站";
|
||||
this.detailAmount = row.h5Amount;
|
||||
}else if (status === 5) {
|
||||
this.detailType = "补扣";
|
||||
this.detailAmount = row.deductionAmount;
|
||||
}
|
||||
this.getDetailList(status);
|
||||
},
|
||||
// 新增一个方法,获取对应金额
|
||||
getAmountByStatus(row, status) {
|
||||
switch (status) {
|
||||
case 1: return row.reserveAmount;
|
||||
case 2: return row.h5Amount;
|
||||
case 3: return row.canteenAmount;
|
||||
case 4: return row.superAmount;
|
||||
default: return 0;
|
||||
}
|
||||
},
|
||||
/** 获取详情分页数据 */
|
||||
getDetailList(status) {
|
||||
const params = {
|
||||
conSource: status,
|
||||
orgName: this.detail.orgName,
|
||||
pageNum: this.detailParams.pageNum,
|
||||
pageSize: this.detailParams.pageSize,
|
||||
startPayTime: this.queryParams.startPayTime,
|
||||
endPayTime: this.queryParams.endPayTime,
|
||||
};
|
||||
getDetailList(params).then((res) => {
|
||||
this.detailData = res || [];
|
||||
this.detailTotal = res.total || 0;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clickable {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
}
|
||||
.clickable:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.detail-dialog ::v-deep .el-table th {
|
||||
background: #f5f7fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询条件 -->
|
||||
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
||||
|
||||
<!-- <el-form-item label="所属组织">
|
||||
<el-input v-model="queryParams.orgName" placeholder="请输入组织名称" clearable />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="所属组织">
|
||||
<el-cascader
|
||||
v-model="selectedOrg"
|
||||
:options="orgOptions"
|
||||
:show-all-levels="false"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择所属组织"
|
||||
:props="{
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'hover',
|
||||
value: 'orgId',
|
||||
label: 'orgName',
|
||||
children: 'children'
|
||||
}"
|
||||
style="width: 260px;"
|
||||
>
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户姓名">
|
||||
<el-input v-model="queryParams.custName" placeholder="请输入组织名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="支付开始时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.startPayTime"
|
||||
type="datetime"
|
||||
placeholder="选择开始时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付结束时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.endPayTime"
|
||||
type="datetime"
|
||||
placeholder="选择结束时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button type="success" @click="newexportExcel">导出列表</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 主表格 -->
|
||||
<el-table
|
||||
:data="tableData.slice((pageNum-1)*pageSize,pageNum*pageSize)"
|
||||
border
|
||||
style="width: 100%"
|
||||
:header-cell-style="tableHeaderStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
v-loading="loading"
|
||||
element-loading-text="数据加载中..."
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(255, 255, 255, 0.8)"
|
||||
>
|
||||
<!-- 序号列:连续分页序号 -->
|
||||
<el-table-column
|
||||
label="序号"
|
||||
align="center"
|
||||
type="index"
|
||||
:index="indexMethod"
|
||||
width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
label="所属组织"
|
||||
prop="orgFullName"
|
||||
align="center"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
|
||||
<el-table-column label="用户姓名" prop="custName" align="center" />
|
||||
<el-table-column label="用户编号" prop="custId" align="center" />
|
||||
<el-table-column label="订单类型" prop="flowType" align="center">
|
||||
<template #default="scope">
|
||||
<span :style="{ color: getFlowTypeColor(scope.row.flowType), fontWeight: 'bold' }">
|
||||
{{ getFlowTypeLabel(scope.row.flowType) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="订单金额" align="center">
|
||||
<template v-slot="scope">
|
||||
{{ (Math.abs(scope.row.amount) / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="用户手机号" prop="phone" align="center" />
|
||||
<el-table-column label="下单时间" prop="ordTime" align="center" />
|
||||
<el-table-column label="备注" prop="remark" align="center" />
|
||||
</el-table>
|
||||
|
||||
<!-- 主表分页 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<el-dialog
|
||||
:visible.sync="detailVisible"
|
||||
:title="detail.orgName + ' - 消费详情'"
|
||||
width="1400px"
|
||||
class="detail-dialog"
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
style="margin-bottom: 10px;"
|
||||
@click="exportDetailExcel"
|
||||
>
|
||||
导出详情
|
||||
</el-button>
|
||||
|
||||
<el-table
|
||||
:data="detailData"
|
||||
border
|
||||
style="width: 100%"
|
||||
height="600px"
|
||||
:header-cell-style="tableHeaderStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
>
|
||||
<el-table-column label="用户姓名" prop="custName" align="center" />
|
||||
<el-table-column label="用户编号" prop="custId" align="center" />
|
||||
<el-table-column label="所属组织" prop="orgFullName" align="center" />
|
||||
<el-table-column label="订单类型" prop="consumeSource" align="center" />
|
||||
<el-table-column label="订单金额" prop="amount" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ (scope.row.amount / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="用户手机号" prop="phone" align="center" />
|
||||
<el-table-column label="下单时间" prop="ordTime" align="center" />
|
||||
<el-table-column label="备注" prop="remark" align="center" />
|
||||
</el-table>
|
||||
|
||||
<!-- 详情分页 -->
|
||||
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">关闭</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getTree, peoplelistRecord,download} from "@/api/canteen/canteenRecord";
|
||||
import ExcelJS from "exceljs";
|
||||
import { saveAs } from "file-saver";
|
||||
export default {
|
||||
data() {
|
||||
const today = new Date();
|
||||
const startOfDay = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(today.getDate()).padStart(2,"0")} 00:00:00`;
|
||||
const endOfDay = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2,"0")}-${String(today.getDate()).padStart(2,"0")} 23:59:59`;
|
||||
return {
|
||||
selectedOrg: [], // 支持多选
|
||||
orgOptions:[],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
startPayTime: startOfDay,
|
||||
endPayTime: endOfDay,
|
||||
orgName: "",
|
||||
},
|
||||
detailVisible: false,
|
||||
detail: {},
|
||||
tableData: [],
|
||||
total: 0,
|
||||
detailData: [],
|
||||
detailTotal: 0,
|
||||
detailParams: { pageNum: 1, pageSize: 20 },
|
||||
loading: false,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getTree();
|
||||
},
|
||||
methods: {
|
||||
getTree(){
|
||||
getTree().then(res => {
|
||||
this.orgOptions = res;
|
||||
});
|
||||
},
|
||||
// 递归获取节点及子节点的所有 orgId
|
||||
getAllChildIds(node) {
|
||||
let ids = [node.orgId]; // 当前节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
ids = ids.concat(this.getAllChildIds(child)); // 递归获取子节点
|
||||
});
|
||||
}
|
||||
return ids;
|
||||
},
|
||||
|
||||
// 根据 cascader 的选中路径获取所有要传的 orgId
|
||||
getSelectedOrgIds() {
|
||||
if (!this.selectedOrg || this.selectedOrg.length === 0) return [];
|
||||
|
||||
const lastValue = this.selectedOrg[this.selectedOrg.length - 1];
|
||||
|
||||
// 找到对应节点
|
||||
let stack = [...this.orgOptions];
|
||||
let node = null;
|
||||
for (let val of this.selectedOrg) {
|
||||
node = stack.find(item => item.orgId === val); // ⚠️ 改成 orgId
|
||||
if (!node) break;
|
||||
stack = node.children || [];
|
||||
}
|
||||
|
||||
if (node) {
|
||||
return this.getAllChildIds(node); // 找到则递归所有子节点 orgId
|
||||
}
|
||||
return [lastValue]; // 没找到就只返回最后一级
|
||||
},
|
||||
indexMethod(index) {
|
||||
return (this.queryParams.pageNum - 1) * this.queryParams.pageSize + index + 1;
|
||||
},
|
||||
// 返回文字标签
|
||||
getFlowTypeLabel(flowType) {
|
||||
flowType = Number(flowType || 0);
|
||||
if (flowType === 110) return "消费";
|
||||
if (flowType === 130) return "退款";
|
||||
if (flowType === 120) return "消费补扣";
|
||||
return "其他";
|
||||
},
|
||||
// 返回颜色
|
||||
getFlowTypeColor(flowType) {
|
||||
flowType = Number(flowType || 0);
|
||||
if (flowType === 110) return "red"; // 消费红色
|
||||
if (flowType === 130) return "green"; // 退款绿色
|
||||
return "black";
|
||||
},
|
||||
tableHeaderStyle() { return { background: "#f5f7fa", fontWeight: "bold", textAlign: "center" }; },
|
||||
tableCellStyle() { return { textAlign: "center" }; },
|
||||
|
||||
handleQuery() {
|
||||
if(this.queryParams.startPayTime && this.queryParams.endPayTime && this.queryParams.endPayTime < this.queryParams.startPayTime){
|
||||
this.$message.error("结束时间不能早于开始时间");
|
||||
return;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 取最后一级 orgId
|
||||
this.queryParams.selectedOrg = this.getSelectedOrgIds(); // 二级或三级下的所有 id
|
||||
console.log("11111"+ this.queryParams.selectedOrg)
|
||||
// queryParams.orgPath = this.selectedOrg.join(',');
|
||||
peoplelistRecord(this.queryParams).then(res => {
|
||||
this.tableData = res.rows || [];
|
||||
this.total = Number(res.total) || 0; // 转成数字
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出主表 */
|
||||
newexportExcel(){
|
||||
this.queryParams.selectedOrg = this.getSelectedOrgIds(); // 二级或三级下的所有 id
|
||||
this.download('/smart-canteen/api/v2/report/consume/exportExcel', { ...this.queryParams }, `人员信息报表_${Date.now()}.xlsx`)
|
||||
},
|
||||
handleDetail(row) {
|
||||
this.detail = row;
|
||||
this.detailVisible = true;
|
||||
this.detailParams.pageNum = 1;
|
||||
this.getDetailList();
|
||||
},
|
||||
|
||||
getDetailList() {
|
||||
const params = {
|
||||
orgName: this.detail.orgName,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
startPayTime: this.queryParams.startPayTime,
|
||||
endPayTime: this.queryParams.endPayTime,
|
||||
};
|
||||
getDetailList(params).then(res => {
|
||||
this.detailData = res.list || [];
|
||||
this.detailTotal = res.total || 0;
|
||||
});
|
||||
},
|
||||
|
||||
exportExcel() {
|
||||
if(!this.tableData || this.tableData.length === 0) {
|
||||
this.$message.warning("暂无数据可导出");
|
||||
return;
|
||||
}
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet("消费统计");
|
||||
|
||||
sheet.columns = [
|
||||
{ header: "用户姓名", key: "custName", width: 15 },
|
||||
{ header: "用户编号", key: "custId", width: 20 },
|
||||
{ header: "所属组织", key: "orgFullName", width: 30 },
|
||||
{ header: "订单类型", key: "consumeSource", width: 15 },
|
||||
{ header: "订单金额", key: "amount", width: 15 },
|
||||
{ header: "用户手机号", key: "phone", width: 15 },
|
||||
{ header: "下单时间", key: "ordTime", width: 20 },
|
||||
{ header: "备注", key: "remark", width: 25 },
|
||||
];
|
||||
|
||||
this.tableData.forEach(item => sheet.addRow({
|
||||
custName: item.custName || "",
|
||||
custId: item.custId || "",
|
||||
orgFullName: item.orgFullName || "",
|
||||
flow_type_name: item.flow_type_name || "",
|
||||
consumeSource: item.consumeSource || "",
|
||||
ordDate: item.ordDate || "",
|
||||
amount: item.amount || 0,
|
||||
phone: item.phone || "",
|
||||
ordTime: item.ordTime || "",
|
||||
remark: item.remark || "",
|
||||
}));
|
||||
|
||||
sheet.eachRow((row,rowNumber)=>{
|
||||
row.eachCell(cell=>{
|
||||
cell.alignment={vertical:"middle",horizontal:"center"};
|
||||
cell.border={
|
||||
top:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
left:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
bottom:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
right:{style:"thin",color:{argb:"FFCCCCCC"}}
|
||||
};
|
||||
if(rowNumber===1) cell.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFEAEAEA"}};
|
||||
});
|
||||
});
|
||||
|
||||
workbook.xlsx.writeBuffer().then(buffer=>{
|
||||
saveAs(new Blob([buffer],{type:"application/octet-stream"}), `消费统计_${new Date().toLocaleDateString().replace(/\//g,"-")}.xlsx`);
|
||||
});
|
||||
},
|
||||
|
||||
/** 导出详情 */
|
||||
exportDetailExcel() {
|
||||
if(!this.detailData || this.detailData.length===0){
|
||||
this.$message.warning("暂无详情数据可导出");
|
||||
return;
|
||||
}
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet("消费详情");
|
||||
|
||||
sheet.columns = [
|
||||
{ header: "用户姓名", key: "custName", width: 15 },
|
||||
{ header: "用户编号", key: "custId", width: 20 },
|
||||
{ header: "所属组织", key: "orgFullName", width: 30 },
|
||||
{ header: "订单类型", key: "consumeSource", width: 15 },
|
||||
{ header: "就餐日期", key: "ordDate", width: 18 },
|
||||
{ header: "订单金额", key: "amount", width: 15 },
|
||||
{ header: "用户手机号", key: "phone", width: 15 },
|
||||
{ header: "下单时间", key: "ordTime", width: 20 },
|
||||
{ header: "备注", key: "remark", width: 25 },
|
||||
];
|
||||
|
||||
this.detailData.forEach(item=>sheet.addRow({
|
||||
custName: item.custName || "",
|
||||
custId: item.custId || "",
|
||||
orgFullName: item.orgFullName || "",
|
||||
flow_type_name: item.flow_type_name || "",
|
||||
consumeSource: item.consumeSource || "",
|
||||
ordDate: item.ordDate || "",
|
||||
amount: item.amount || 0,
|
||||
phone: item.phone || "",
|
||||
ordTime: item.ordTime || "",
|
||||
remark: item.remark || "",
|
||||
}));
|
||||
|
||||
sheet.eachRow((row,rowNumber)=>{
|
||||
row.eachCell(cell=>{
|
||||
cell.alignment={vertical:"middle",horizontal:"center"};
|
||||
cell.border={
|
||||
top:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
left:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
bottom:{style:"thin",color:{argb:"FFCCCCCC"}},
|
||||
right:{style:"thin",color:{argb:"FFCCCCCC"}}
|
||||
};
|
||||
if(rowNumber===1) cell.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFEAEAEA"}};
|
||||
});
|
||||
});
|
||||
|
||||
workbook.xlsx.writeBuffer().then(buffer=>{
|
||||
saveAs(new Blob([buffer],{type:"application/octet-stream"}), `消费详情_${this.detail.orgName}_${new Date().toLocaleDateString().replace(/\//g,"-")}.xlsx`);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clickable { color:#409eff; cursor:pointer; font-weight:500; }
|
||||
.clickable:hover { text-decoration: underline; }
|
||||
.detail-dialog ::v-deep .el-table th { background: #f5f7fa; font-weight: 600; }
|
||||
</style>
|
||||
Loading…
Reference in New Issue