供应链基础模块提交

This commit is contained in:
lizhenhua 2025-11-10 10:49:10 +08:00
parent 0a8f1b6556
commit 82abf1cb8f
7 changed files with 571 additions and 485 deletions

View File

@ -43,6 +43,15 @@ export function getplaceList(query) {
})
}
//获取异地消费汇总
export function getplaceListhz(query) {
return request({
url: '/smart-canteen/api/v2/report/getplacehzList',
method: 'post',
data: query
})
}
// 查询详情列表
export function getDetailList(query) {
return request({

View File

@ -74,6 +74,26 @@ export const constantRoutes = [
}
]
},
{//供应链-库存管理-库存盘点
path: '/inventoryCount',
component: Layout,
hidden: true,
redirect: 'noredirect',
children: [
{
path: 'inventoryCountDetail',
component: () => import('@/views/inventoryCount/detail'),
name: 'InventoryCountDetail',
meta: { title: '盘点详情', icon: '' }
},
{
path: 'inventoryCountEdit',
component: () => import('@/views/inventoryCount/edit'),
name: 'InventoryCountEdit',
meta: { title: '盘点新增/编辑', icon: '' }
},
]
},
{
path: '/user',
component: Layout,

View File

@ -8,7 +8,7 @@ import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import { encryptCBC, decryptCBC } from '@/utils/aescbc'
import { CONFIG } from '@/utils/configure'
import { hashWithSM3AndSalt } from '@/utils/sm'
import { hashWithSM3AndSalt ,encryptWithSM4,decryptWithSM4} from '@/utils/sm'
//let token = localStorage.getItem("tokens");
@ -23,7 +23,7 @@ const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 30000
timeout: 80000
})
// request 拦截器
@ -86,7 +86,7 @@ service.interceptors.request.use(config => {
}
// 加密数据
if (CONFIG.dataSettings.encryptRequest && encryptRequest) {
config.data = encryptCBC(data)
config.data = encryptWithSM4(data)
}
}
// 检查请求数据大小
@ -117,7 +117,7 @@ service.interceptors.request.use(config => {
service.interceptors.response.use(res => {
console.log(res)
if (res.headers.encryptresponse && !res.data.hasOwnProperty('code')) {
res.data = JSON.parse(decryptCBC(res.data))
res.data = JSON.parse(decryptWithSM4(res.data))
console.log(res.data)
}
// 未设置状态码则默认成功状态

View File

@ -47,4 +47,3 @@ export function encryptWithSM4(plainText) {
export function decryptWithSM4(cipherText){
return SM4.decrypt(cipherText, SM_CONFIG.SM4_KEY,{ mode: 'cbc', padding: 'pkcs#5' ,iv:SM_CONFIG.SM4_SALT});
}

View File

@ -71,6 +71,13 @@
</span>
</template>
</el-table-column>
<el-table-column label="茶歇消费" prop="h5Amount" align="center">
<template slot-scope="scope">
<span class="clickable" @click="handleDetail(scope.row,6)">
{{ Math.abs(scope.row.teabreakAmount) }}
</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)">
@ -89,6 +96,7 @@
Math.abs(scope.row.canteenAmount || 0) +
Math.abs(scope.row.superAmount || 0) +
Math.abs(scope.row.deductionAmount || 0) +
Math.abs(scope.row.teabreakAmount || 0) +
Math.abs(scope.row.h5Amount || 0)
).toFixed(2)
}}
@ -152,7 +160,7 @@
</el-table-column>
<el-table-column label="消费类型" prop="canteenAmount" align="center">
<template slot-scope="scope">
<span class="clickable" @click="handleDetail(scope.row)">
<span class="clickable">
<span :style="{ color: getConsumeTypeColor(scope.row) }">
{{ getConsumeTypeLabel(scope.row) }}
</span>
@ -236,21 +244,22 @@ export default {
},
computed: {
pageTotals() {
const totals = { reserve: 0, canteen: 0, super: 0, h5: 0, deduction: 0, total: 0 };
const totals = { reserve: 0, canteen: 0, super: 0, h5: 0, deduction: 0,teabreak: 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);
const teabreak = Math.abs(Number(row.teabreakAmount) || 0);
totals.reserve += reserve;
totals.canteen += canteen;
totals.super += sup;
totals.h5 += h5;
totals.teabreak += teabreak;
totals.deduction += deduction;
});
totals.total = totals.reserve + totals.canteen + totals.super + totals.h5 + totals.deduction;
totals.total = totals.reserve + totals.canteen + totals.super + totals.h5 + totals.deduction+totals.teabreak ;
return totals;
}
},
@ -265,11 +274,11 @@ export default {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet("消费统计");
//
const header = ["食堂名称", "预订餐消费", "食堂消费", "超市消费", "驿站消费","消费补扣","总和"];
// -
const header = ["食堂名称", "预订餐消费", "食堂消费", "超市消费", "驿站消费", "茶歇消费", "消费补扣", "总和"];
sheet.addRow(header);
//
// -
this.tableData.forEach(item => {
sheet.addRow([
item.orgName,
@ -277,28 +286,30 @@ export default {
Math.abs(item.canteenAmount || 0),
Math.abs(item.superAmount || 0),
Math.abs(item.h5Amount || 0),
Math.abs(item.teabreakAmount || 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)
Math.abs(item.h5Amount || 0) +
Math.abs(item.teabreakAmount || 0) + //
Math.abs(item.deductionAmount || 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 },
{ header: "消费补扣", key: "payTime", width: 30 },
{ header: "总和", key: "payTime", width: 30 }
];
// + -
sheet.columns = [
{ header: "食堂名称", key: "orgFullName", width: 40 },
{ header: "预订餐消费", key: "reserveAmount", width: 10 },
{ header: "食堂消费", key: "canteenAmount", width: 10 },
{ header: "超市消费", key: "superAmount", width: 10 },
{ header: "驿站消费", key: "h5Amount", width: 10 },
{ header: "茶歇消费", key: "teabreakAmount", width: 10 }, //
{ header: "消费补扣", key: "deductionAmount", width: 10 },
{ header: "总和", key: "total", width: 10 }
];
//
sheet.getRow(1).eachCell(cell => {
@ -337,7 +348,7 @@ export default {
const fileName = `消费统计_${new Date().toLocaleDateString().replace(/\//g, "-")}.xlsx`;
saveAs(new Blob([buffer], { type: "application/octet-stream" }), fileName);
});
},
},
/** 导出详情表格 */
exportDetailExcel() {
@ -493,6 +504,9 @@ export default {
}else if (status === 5) {
this.detailType = "补扣";
this.detailAmount = row.deductionAmount;
}else if (status === 6) {
this.detailType = "茶歇";
this.detailAmount = row.teabreakAmount;
}
this.getDetailList(status);
},

View File

@ -1,478 +1,522 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="日期时间">
<el-date-picker
v-model="dateRange"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd" style="width: 340px"
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions" >
</el-date-picker>
</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: 200px;"
>
</el-cascader>
</el-form-item>
<el-form-item label="工作地">
<el-cascader
v-model="gzselectedOrg"
:options="gzorgOptions"
: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>
<div class="app-container">
<!-- 查询条件 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="日期时间">
<el-date-picker
v-model="dateRange"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
style="width: 340px"
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="success" @click="newexportExcel">导出列表</el-button>
</el-form-item>
</el-form>
<el-form-item label="消费地*">
<el-cascader
v-model="selectedOrg"
:options="orgOptions"
:show-all-levels="false"
clearable
filterable
placeholder="请选择消费地"
:props="cascaderProps"
collapse-tags
collapse-tags-tooltip
style="width: 200px;"
@change="handleOrgChange"
></el-cascader>
</el-form-item>
<el-table v-loading="loading" :data="tableListData" >
<el-table-column
label="序号"
align="center"
width="80"
>
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">合计</span>
<span v-else>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="用户账号" align="center" prop="custNum" :show-overflow-tooltip="true" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.custNum }}</span>
</template>
</el-table-column>
<el-table-column label="用户姓名" align="center" prop="custName" :show-overflow-tooltip="true" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.custName }}</span>
</template>
</el-table-column>
<el-table-column label="用户手机号" align="center" prop="mobile" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.mobile }}</span>
</template>
</el-table-column>
<el-table-column label="所属组织" align="center" prop="orgFullName" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.orgFullName }}</span>
</template>
</el-table-column>
<el-table-column label="订单类型" align="center" prop="orderType" :show-overflow-tooltip="true" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.orderType }}</span>
</template>
</el-table-column>
<el-table-column label="交易次数" align="center" prop="tradeNum" :show-overflow-tooltip="true" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary" style="font-weight: bold; color: #409EFF;">{{ scope.row.tradeNum }}</span>
<span v-else>{{ scope.row.tradeNum }}</span>
</template>
</el-table-column>
<el-table-column label="交易余额" align="center" prop="payableAmount" :show-overflow-tooltip="true" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary" style="font-weight: bold; color: #409EFF;">{{ (scope.row.payableAmount/100).toFixed(2) }}</span>
<span v-else>{{ (scope.row.payableAmount/100).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="消费地" align="center" prop="areaName" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.areaName }}</span>
</template>
</el-table-column>
<el-table-column label="工作地" align="center" prop="workAreaName" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.workAreaName }}</span>
</template>
</el-table-column>
</el-table>
<el-form-item label="工作地*">
<el-cascader
v-model="gzselectedOrg"
:options="gzorgOptions"
:show-all-levels="false"
clearable
filterable
placeholder="请选择工作地"
:props="cascaderProps"
collapse-tags
collapse-tags-tooltip
style="width: 200px;"
@change="handleGzOrgChange"
></el-cascader>
</el-form-item>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getplaceList"
/>
</div>
</template>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="success" @click="newexportExcel">导出列表</el-button>
</el-form-item>
</el-form>
<script>
import { getTreeArea, getplaceList, getplaceListApi } from "@/api/canteen/canteenRecord";
export default {
name: "",
dicts: [],
data() {
return {
orgOptions:[],
selectedOrg: [], //
gzorgOptions:[], //
gzselectedOrg: [], //
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
tableListData: [],
//
showSummary: false,
//
summaryData: {
tradeNum: 0,
payableAmount: 0
},
//
deptOptions:[],
//
queryParams: {
startTime: '', //
endTime: '', //
pageNum: 1,
pageSize: 10,
deptIdList:[],
searchValue:null,
userType:null,
selectedOrg: [], // ID
gzselectedOrg: [] // ID
},
dateRange:this.defaultDateRange(),
pickerOptions: {
shortcuts: [{
<!-- 数据表格 -->
<el-table v-loading="loading" :data="tableListData">
<el-table-column label="序号" align="center" width="80">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">合计</span>
<span v-else>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="用户账号" align="center" prop="custNum" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.custNum }}</span>
</template>
</el-table-column>
<el-table-column label="用户姓名" align="center" prop="custName" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.custName }}</span>
</template>
</el-table-column>
<el-table-column label="手机号" align="center" prop="mobile">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.mobile }}</span>
</template>
</el-table-column>
<el-table-column label="所属组织" align="center" prop="orgFullName">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.orgFullName }}</span>
</template>
</el-table-column>
<el-table-column label="订单类型" align="center" prop="orderType" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.orderType }}</span>
</template>
</el-table-column>
<el-table-column label="交易次数" align="center" prop="tradeNum" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary" style="font-weight: bold; color: #409EFF;">{{ scope.row.tradeNum }}</span>
<span v-else>{{ scope.row.tradeNum }}</span>
</template>
</el-table-column>
<el-table-column label="交易金额" align="center" prop="payableAmount" width="120">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary" style="font-weight: bold; color: #409EFF;">{{ (scope.row.payableAmount/100).toFixed(2) }}</span>
<span v-else>{{ (scope.row.payableAmount/100).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="消费地" align="center" prop="areaName">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.areaName }}</span>
</template>
</el-table-column>
<el-table-column label="工作地" align="center" prop="workAreaName">
<template slot-scope="scope">
<span v-if="scope.$index === tableListData.length - 1 && showSummary">-</span>
<span v-else>{{ scope.row.workAreaName }}</span>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="handlePagination"
/>
</div>
</template>
<script>
import { getTreeArea, getplaceList } from "@/api/canteen/canteenRecord";
export default {
name: "异地消费报表",
data() {
return {
orgOptions: [],
selectedOrg: [],
gzorgOptions: [],
gzselectedOrg: [],
loading: true,
showSearch: true,
total: 0,
tableListData: [],
showSummary: false,
summaryData: { tradeNum: 0, payableAmount: 0 },
dateRange: [],
pickerOptions: {
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
},
{
text: '最近一个月',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
},
};
},
created() {
this.getTree();
this.getplaceList();
},
methods: {
//
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计';
return;
}
switch (column.property) {
case 'tradeNum':
sums[index] = this.summaryData.tradeNum;
break;
case 'payableAmount':
sums[index] = (this.summaryData.payableAmount / 100).toFixed(2);
break;
default:
sums[index] = '-';
}
});
return sums;
},
]
},
indexMethod(index) {
return (this.queryParams.pageNum - 1) * queryParams.pageSize + index + 1;
queryParams: {
pageNum: 1,
pageSize: 10,
selectedOrg: [],
gzselectedOrg: [],
startTime: '',
endTime: '',
userType: null
},
/** 查询部门下拉树结构 */
getTree(){
getTreeArea().then(res => {
this.orgOptions = res;
this.gzorgOptions = JSON.parse(JSON.stringify(res)); //
});
},
// orgId
getAllChildIds(node, options) {
let ids = [node.orgId]; //
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
ids = ids.concat(this.getAllChildIds(child, options)); //
});
}
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);
if (!node) break;
stack = node.children || [];
}
if (node) {
return this.getAllChildIds(node, this.orgOptions);
}
return [lastValue];
},
// cascader orgId
getGzSelectedOrgIds() {
if (!this.gzselectedOrg || this.gzselectedOrg.length === 0) return [];
const lastValue = this.gzselectedOrg[this.gzselectedOrg.length - 1];
//
let stack = [...this.gzorgOptions];
let node = null;
for (let val of this.gzselectedOrg) {
node = stack.find(item => item.orgId === val);
if (!node) break;
stack = node.children || [];
}
if (node) {
return this.getAllChildIds(node, this.gzorgOptions);
}
return [lastValue];
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getplaceList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = this.defaultDateRange();
this.selectedOrg = [];
this.gzselectedOrg = [];
this.queryParams = {
pageNum: 1,
pageSize: 10,
selectedOrg: [],
gzselectedOrg: []
};
this.resetForm("queryForm");
this.handleQuery();
},
/** 查询列表 */
getplaceList() {
this.loading = true;
//
if (this.dateRange && this.dateRange.length === 2) {
const start = this.dateRange[0];
const end = this.dateRange[1];
const formatDate = d => {
const date = new Date(d);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${y}-${m}-${day}`;
};
this.queryParams.startTime = formatDate(start) + ' 00:00:00';
this.queryParams.endTime = formatDate(end) + ' 23:59:59';
}
this.queryParams.selectedOrg = this.getSelectedOrgIds();
this.queryParams.gzselectedOrg = this.getGzSelectedOrgIds();
let param = {
"pageNum": this.queryParams.pageNum,
"pageSize": this.queryParams.pageSize,
"selectedOrg": this.queryParams.selectedOrg,
"gzselectedOrg": this.queryParams.gzselectedOrg,
"userType": this.queryParams.userType,
"startTime": this.queryParams.startTime,
"endTime": this.queryParams.endTime
};
getplaceList(param).then(response => {
this.tableListData = response.rows || [];
this.total = Number(response.total) || 0;
//
this.calculateCurrentPageSummary();
this.loading = false;
}).catch(error => {
console.error('获取数据失败:', error);
this.loading = false;
});
},
newexportExcel() {
//
if (this.dateRange && this.dateRange.length === 2) {
const start = this.dateRange[0];
const end = this.dateRange[1];
const formatDate = d => {
const date = new Date(d);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${y}-${m}-${day}`;
};
this.queryParams.startTime = formatDate(start) + ' 00:00:00';
this.queryParams.endTime = formatDate(end) + ' 23:59:59';
}
this.queryParams.selectedOrg = this.getSelectedOrgIds();
this.queryParams.gzselectedOrg = this.getGzSelectedOrgIds();
let param = {
"pageNum": this.queryParams.pageNum,
"pageSize": this.queryParams.pageSize,
"selectedOrg": this.queryParams.selectedOrg,
"gzselectedOrg": this.queryParams.gzselectedOrg,
"userType": this.queryParams.userType,
"startTime": this.queryParams.startTime,
"endTime": this.queryParams.endTime
};
if (param.custName) {
param.custName = encodeURIComponent(params.custName); //
}
//
this.download(
'/smart-canteen/api/v2/report/consume/placeexportExcel',
param,
`异地消费报表_${Date.now()}.xlsx`
);
},
//
calculateCurrentPageSummary() {
let tradeNumTotal = 0;
let payableAmountTotal = 0;
this.tableListData.forEach(item => {
tradeNumTotal += (item.tradeNum || 0);
payableAmountTotal += (item.payableAmount || 0);
});
this.summaryData = {
tradeNum: tradeNumTotal,
payableAmount: payableAmountTotal
};
this.showSummary = this.tableListData.length > 0;
},
defaultDateRange() {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime());
this.start = parseInt(start.getTime() / 1000);
this.end = parseInt(end.getTime() / 1000);
return [start, end];
},
//
formatDateTime(date) {
// YYYY-MM-DD
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0
const day = String(date.getDate()).padStart(2, '0');
const hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
const minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
const seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
//
formatDate(date) {
// YYYY-MM-DD
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
cascaderProps: {
multiple: true,
checkStrictly: true,
expandTrigger: 'hover',
value: 'orgId',
label: 'orgName',
children: 'children'
}
}
};
</script>
};
},
created() {
this.getTree();
this.dateRange = this.defaultDateRange();
},
methods: {
//
defaultDateRange() {
const end = new Date();
const start = new Date();
return [start, end];
},
<style scoped>
/* 为合计行添加特殊样式 */
.el-table ::v-deep .el-table__footer-wrapper tbody td {
background-color: #f5f7fa;
font-weight: bold;
color: #409EFF;
//
getTree() {
getTreeArea().then(res => {
this.orgOptions = res;
this.gzorgOptions = JSON.parse(JSON.stringify(res));
if (res && res.length > 0) {
// ---------- ----------
let defaultConsume = res[0];
if (defaultConsume.children && defaultConsume.children.length > 0) {
//
this.selectedOrg = [[defaultConsume.orgId, defaultConsume.children[0].orgId]];
} else {
//
this.selectedOrg = [[defaultConsume.orgId]];
}
// ---------- ----------
let defaultWork = res[0];
if (defaultWork.children && defaultWork.children.length > 0) {
this.gzselectedOrg = [[defaultWork.orgId, defaultWork.children[0].orgId]];
} else {
this.gzselectedOrg = [[defaultWork.orgId]];
}
//
this.getplaceList();
}
});
},
//
handlePagination(pagination) {
this.queryParams.pageNum = pagination.page;
this.queryParams.pageSize = pagination.limit;
this.getplaceList();
},
handleOrgChange(value) {
this.selectedOrg = value || [];
},
handleGzOrgChange(value) {
this.gzselectedOrg = value || [];
},
findNodeById(nodes, id) {
if (!nodes || !Array.isArray(nodes)) return null;
for (const node of nodes) {
if (node.orgId === id) return node;
if (node.children) {
const found = this.findNodeById(node.children, id);
if (found) return found;
}
}
return null;
},
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;
},
getSelectedOrgIds() {
if (!this.selectedOrg || this.selectedOrg.length === 0) {
return [];
}
let ids = [];
this.selectedOrg.forEach(path => {
if (Array.isArray(path) && path.length > 0) {
const lastId = path[path.length - 1];
const node = this.findNodeById(this.orgOptions, lastId);
if (node) {
ids = ids.concat(this.getAllChildIds(node));
} else {
ids.push(lastId);
}
} else if (typeof path === 'string' || typeof path === 'number') {
const node = this.findNodeById(this.orgOptions, path);
if (node) {
ids = ids.concat(this.getAllChildIds(node));
} else {
ids.push(path);
}
}
});
return [...new Set(ids)];
},
getGzSelectedOrgIds() {
if (!this.gzselectedOrg || this.gzselectedOrg.length === 0) {
return [];
}
let ids = [];
this.gzselectedOrg.forEach(path => {
if (Array.isArray(path) && path.length > 0) {
const lastId = path[path.length - 1];
const node = this.findNodeById(this.gzorgOptions, lastId);
if (node) {
ids = ids.concat(this.getAllChildIds(node));
} else {
ids.push(lastId);
}
} else if (typeof path === 'string' || typeof path === 'number') {
const node = this.findNodeById(this.gzorgOptions, path);
if (node) {
ids = ids.concat(this.getAllChildIds(node));
} else {
ids.push(path);
}
}
});
return [...new Set(ids)];
},
/** 查询操作 */
handleQuery() {
if (!this.selectedOrg.length) {
this.$message({
message: '请选择消费地后再查询!',
type: 'warning',
showClose: true,
duration: 2500,
customClass: 'custom-message-warning'
});
return;
}
if (!this.gzselectedOrg.length) {
this.$message({
message: '请选择工作地后再查询!',
type: 'warning',
showClose: true,
duration: 2500,
customClass: 'custom-message-warning'
});
return;
}
//
this.queryParams.pageNum = 1;
this.getplaceList();
},
/** 重置操作 */
resetQuery() {
this.dateRange = this.defaultDateRange();
//
if (this.orgOptions && this.orgOptions.length > 0) {
this.selectedOrg = [[this.orgOptions[0].orgId]];
this.gzselectedOrg = [[this.gzorgOptions[0].orgId]];
}
//
this.queryParams = {
pageNum: 1,
pageSize: 10,
selectedOrg: [],
gzselectedOrg: [],
startTime: '',
endTime: '',
userType: null
};
//
this.getplaceList();
},
/** 查询列表 */
getplaceList() {
this.loading = true;
//
let startTime = '';
let endTime = '';
if (this.dateRange && this.dateRange.length === 2) {
const start = this.dateRange[0];
const end = this.dateRange[1];
const formatDate = d => {
const date = new Date(d);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${y}-${m}-${day}`;
};
startTime = formatDate(start) + ' 00:00:00';
endTime = formatDate(end) + ' 23:59:59';
}
//
let param = {
pageNum: this.queryParams.pageNum,
pageSize: this.queryParams.pageSize,
startTime: startTime,
endTime: endTime,
selectedOrg: this.getSelectedOrgIds(),
gzselectedOrg: this.getGzSelectedOrgIds(),
userType: this.queryParams.userType
};
console.log('分页请求参数:', param); //
getplaceList(param).then(response => {
this.tableListData = response.rows || [];
this.total = Number(response.total) || 0;
this.calculateCurrentPageSummary();
this.loading = false;
}).catch((error) => {
console.error('查询失败:', error);
this.loading = false;
this.$message.error('查询失败,请重试');
});
},
//
calculateCurrentPageSummary() {
let tradeNumTotal = 0;
let payableAmountTotal = 0;
this.tableListData.forEach(item => {
tradeNumTotal += (item.tradeNum || 0);
payableAmountTotal += (item.payableAmount || 0);
});
this.summaryData = {
tradeNum: tradeNumTotal,
payableAmount: payableAmountTotal
};
this.showSummary = this.tableListData.length > 0;
},
/** 导出Excel */
newexportExcel() {
if (!this.selectedOrg.length || !this.gzselectedOrg.length) {
this.$message.error('请先选择消费地和工作地后再导出!');
return;
}
//
let startTime = '';
let endTime = '';
if (this.dateRange && this.dateRange.length === 2) {
const start = this.dateRange[0];
const end = this.dateRange[1];
const formatDate = d => {
const date = new Date(d);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${y}-${m}-${day}`;
};
startTime = formatDate(start) + ' 00:00:00';
endTime = formatDate(end) + ' 23:59:59';
}
let param = {
pageNum: this.queryParams.pageNum,
pageSize: this.queryParams.pageSize,
selectedOrg: this.getSelectedOrgIds(),
gzselectedOrg: this.getGzSelectedOrgIds(),
userType: this.queryParams.userType,
startTime: startTime,
endTime: endTime
};
//
this.download(
'/smart-canteen/api/v2/report/consume/placeexportExcel',
param,
`异地消费报表_${new Date().getTime()}.xlsx`
);
}
}
</style>
};
</script>
<style scoped>
.el-table ::v-deep .el-table__footer-wrapper tbody td {
background-color: #f5f7fa;
font-weight: bold;
color: #409EFF;
}
/* 添加自定义消息样式 */
.custom-message-warning {
min-width: 200px;
background-color: #fdf6ec;
border: 1px solid #f5dab1;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
color: #e6a23c;
}
/* 为必填项添加星号样式 */
.el-form-item.is-required .el-form-item__label::before {
content: '*';
color: #f56c6c;
margin-right: 4px;
}
</style>

View File

@ -36,7 +36,7 @@ module.exports = {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
// target: `http://localhost:18080`,
target: `http://192.168.0.244:38380`,
target: `http://127.0.0.1:58080`,
// target: `http://192.168.2.74:28080`,
changeOrigin: true,
pathRewrite: {