feat:订单销售统计更新

This commit is contained in:
yangmf_0726 committed 2025-08-29 16:04:57 +08:00
1 parent 4673cc532c
commit 885d9c80b0
2 files changed
+334 -129

No files matched your search

@@ -0,0 +1,62 @@
import request from '@/config/axios'
export interface GetStatisticsDetailRes {
code: number;
data: {
list: {
id: number;
userId: number;
orderId: number;
spuId: number;
spuName: string;
skuId: number;
deviceId: string;
barCode: string;
cabinetChannel: string;
picUrl: string;
count: number;
price: number;
discountPrice: number;
payPrice: number;
orderPartPrice: number;
orderDividePrice: number;
afterSaleStatus: number;
no: string;
createTime: string; // 修改为正确的类型
}[];
total: number;
};
}
// 查询参数接口
export interface StatisticsDetailPageReqVO {
pageNo?: number
pageSize?: number
no?: string // 改为no参数,类型为string
spuId?: number
spuName?: string
userId?: number
deviceId?: string
barCode?: string
createTime?: string[]
afterSaleStatus?: number
}
// 销售统计详情API
export const SalesStatisticsDetailsApi = {
// 查询销售统计详情分页
getStatisticsDetailPage: async (params: StatisticsDetailPageReqVO) => {
return await request.get<GetStatisticsDetailRes>({
url: '/trade/order/statistics-detail',
params
})
},
// 导出销售统计详情 Excel
exportStatisticsDetail: async (params: StatisticsDetailPageReqVO) => {
return await request.download({
url: '/trade/order/export-excel',
params
})
}
}
+272 -129
View File
@@ -1,168 +1,311 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="设备IMEI" prop="deviceId">
<el-input
v-model="queryParams.deviceId"
placeholder="请输入设备IMEI"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="物料编码" prop="barCode">
<el-input
v-model="queryParams.barCode"
placeholder="请输入物料编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="商品名称" prop="spuName">
<el-input
v-model="queryParams.spuName"
placeholder="请输入商品名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" />
搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" />
重置
</el-button>
<el-button
type="primary"
plain
@click="handleExport"
:loading="exportLoading"
<div class="app-container">
<!-- 搜索表单 -->
<el-card class="box-card" shadow="never">
<el-form
ref="queryFormRef"
:model="queryParams"
:inline="true"
label-width="68px"
>
<el-form-item label="订单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入订单号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="设备ID" prop="deviceId">
<el-input
v-model="queryParams.deviceId"
placeholder="请输入设备ID"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="条形码" prop="barCode">
<el-input
v-model="queryParams.barCode"
placeholder="请输入条形码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" />
搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" />
重置
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
>
<Icon icon="ep:download" class="mr-5px" />
导出
</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 数据表格 -->
<el-card class="box-card" shadow="never">
<el-table
v-loading="loading"
:data="list"
stripe
border
style="width: 100%"
:default-sort="{prop: 'createTime', order: 'descending'}"
>
<el-table-column label="订单ID" prop="orderId" width="100" />
<el-table-column label="用户ID" prop="userId" width="100" />
<el-table-column label="订单号" prop="no" width="150" />
<el-table-column label="商品信息" min-width="200">
<template #default="{ row }">
<div class="flex items-center">
<el-image
v-if="row.picUrl"
:src="row.picUrl"
class="w-50px h-50px mr-10px"
fit="cover"
/>
<div>
<div class="font-bold">{{ row.spuName }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="设备信息" min-width="150">
<template #default="{ row }">
<div>
<div>设备ID: {{ row.deviceId }}</div>
<div class="text-sm text-gray-500">货道: {{ row.cabinetChannel }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="条形码" prop="barCode" width="120" />
<el-table-column label="数量" prop="count" width="80" align="center" />
<el-table-column label="原价" width="120" align="center">
<template #default="{ row }">
¥{{ (row.price / 100).toFixed(2) }}
</template>
</el-table-column>
<el-table-column label="实付" width="120" align="center">
<template #default="{ row }">
¥{{ (row.payPrice / 100).toFixed(2) }}
</template>
</el-table-column>
<el-table-column
label="创建时间"
prop="createTime"
width="180"
sortable
:sort-orders="['descending', 'ascending']"
>
<Icon icon="ep:download" class="mr-5px" />
导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<template #default="{ row }">
{{ formatTime(row.createTime) }}
</template>
</el-table-column>
</el-table>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" stripe>
<el-table-column label="物料编码" align="center" prop="barCode" min-width="120" />
<el-table-column label="商品名称" align="center" prop="spuName" min-width="150" show-overflow-tooltip />
<el-table-column label="销售数量" align="center" prop="orderCount" min-width="100">
<template #default="scope">
<el-tag type="success">{{ scope.row.orderCount }}</el-tag>
</template>
</el-table-column>
<el-table-column label="设备IMEI" align="center" prop="deviceId" min-width="120" />
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="handlePageChange"
/>
</el-card>
</div>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import { OrderSalesStatisticsApi } from '@/api/mall/trade/order/salesStatistics'
import { GetSalesStatisticsReqVO } from '@/api/mall/trade/order/salesStatistics'
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { SalesStatisticsDetailsApi, type StatisticsDetailPageReqVO } from '@/api/mall/trade/order/salesStatisticsdetails'
import download from '@/utils/download'
/** 订单销售统计 */
defineOptions({ name: 'OrderSalesStatistics' })
defineOptions({ name: 'TradeSalesStatistics' })
const message = useMessage() // 消息弹窗
// const { t } = useI18n() // 国际化
const loading = ref(true)
const exportLoading = ref(false)
const list = ref<any[]>([])
const total = ref(0)
const queryFormRef = ref()
const allData = ref<any[]>([])
const loading = ref(true) // 列表的加载中
const list = ref<any[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive<GetSalesStatisticsReqVO>({
const queryParams = reactive<StatisticsDetailPageReqVO>({
pageNo: 1,
pageSize: 100,
createTime: ['2025-01-01 00:00:00', '2026-01-01 23:59:59'],
deviceId: undefined,
barCode: undefined,
spuName: undefined,
pageSize: 10,
no: '',
spuId: undefined,
spuName: '',
userId: undefined,
deviceId: '',
barCode: '',
createTime: undefined,
afterSaleStatus: undefined
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
const getAllData = async () => {
loading.value = true
try {
const data = await OrderSalesStatisticsApi.getSalesStatistics(queryParams)
list.value = data.list
total.value = data.total
console.log("销售订单",data)
const firstPageData = await SalesStatisticsDetailsApi.getStatisticsDetailPage({
...queryParams,
pageNo: 1,
pageSize: 1000
})
if (firstPageData && firstPageData.list) {
const sortedData = firstPageData.list.sort((a: any, b: any) => {
return new Date(b.createTime).getTime() - new Date(a.createTime).getTime()
})
allData.value = sortedData
total.value = firstPageData.total || 0
updateCurrentPageData()
console.log("销售订单", firstPageData)
}
} catch (error) {
console.error('获取数据失败:', error)
ElMessage.error('获取数据失败')
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const updateCurrentPageData = () => {
const startIndex = (queryParams.pageNo - 1) * queryParams.pageSize
const endIndex = startIndex + queryParams.pageSize
if (queryParams.no || queryParams.deviceId || queryParams.barCode || queryParams.createTime) {
handleQuery()
} else {
list.value = allData.value.slice(startIndex, endIndex)
}
}
const handlePageChange = () => {
updateCurrentPageData()
}
const handleQuery = () => {
queryParams.pageNo = 1
getList()
let filteredData = [...allData.value]
if (queryParams.no && queryParams.no.trim()) {
filteredData = filteredData.filter((item: any) =>
String(item.no || '').toLowerCase().includes(String(queryParams.no).toLowerCase())
)
}
if (queryParams.deviceId && queryParams.deviceId.trim()) {
filteredData = filteredData.filter((item: any) =>
item.deviceId && String(item.deviceId).toLowerCase().includes(queryParams.deviceId.toLowerCase())
)
}
if (queryParams.barCode && queryParams.barCode.trim()) {
filteredData = filteredData.filter((item: any) =>
item.barCode && String(item.barCode).toLowerCase().includes(queryParams.barCode.toLowerCase())
)
}
if (queryParams.createTime && Array.isArray(queryParams.createTime) && queryParams.createTime.length === 2) {
const startTime = new Date(queryParams.createTime[0]).getTime()
const endTime = new Date(queryParams.createTime[1]).getTime()
filteredData = filteredData.filter((item: any) => {
const itemTime = new Date(item.createTime).getTime()
return itemTime >= startTime && itemTime <= endTime
})
}
const sortedData = filteredData.sort((a: any, b: any) => {
return new Date(b.createTime).getTime() - new Date(a.createTime).getTime()
})
total.value = sortedData.length
const startIndex = (queryParams.pageNo - 1) * queryParams.pageSize
const endIndex = startIndex + queryParams.pageSize
list.value = sortedData.slice(startIndex, endIndex)
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
if (queryFormRef.value) {
queryFormRef.value.resetFields()
}
total.value = allData.value.length
updateCurrentPageData()
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await OrderSalesStatisticsApi.exportSalesStatistics(queryParams)
download.excel(data, `订单销售统计_${new Date().getTime()}.xls`)
console.log('导出成功', data)
await ElMessageBox.confirm('是否确认导出销售统计详情数据?', '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
} catch {
// 用户取消导出或导出失败
exportLoading.value = true
const res = await SalesStatisticsDetailsApi.exportStatisticsDetail(queryParams)
download.excel(res, '销售统计详情.xls')
} catch (error) {
if (error !== 'cancel') {
console.error('导出失败:', error)
ElMessage.error('导出失败')
}
} finally {
exportLoading.value = false
}
}
const formatTime = (timestamp: number | string) => {
if (!timestamp) return '-'
const date = new Date(Number(timestamp))
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
}
/** 初始化 **/
onMounted(() => {
getList()
getAllData()
})
</script>
<style scoped>
.app-container {
padding: 20px;
}
.box-card {
margin-bottom: 20px;
}
.box-card:last-child {
margin-bottom: 0;
}
</style>