|
@@ -4,16 +4,82 @@ const props = withDefaults(
|
|
title: string
|
|
title: string
|
|
data?: any[] | (() => any[])
|
|
data?: any[] | (() => any[])
|
|
totalData?: any | (() => any)
|
|
totalData?: any | (() => any)
|
|
|
|
+ remote?: boolean
|
|
|
|
+ queryReportFun?: (v: any) => Promise<any>
|
|
|
|
+ generateReportFun?: (v: any) => Promise<any>
|
|
reportGenDate?: string
|
|
reportGenDate?: string
|
|
reportType?: "COOP" | "EGG"
|
|
reportType?: "COOP" | "EGG"
|
|
reportDateType?: "D" | "M" | "Q" | "Y"
|
|
reportDateType?: "D" | "M" | "Q" | "Y"
|
|
|
|
+ showQueryButon?: boolean
|
|
|
|
+ showGenerateButton?: boolean
|
|
}>(),
|
|
}>(),
|
|
{
|
|
{
|
|
reportType: "COOP",
|
|
reportType: "COOP",
|
|
- reportDateType: "D"
|
|
|
|
|
|
+ reportDateType: "D",
|
|
|
|
+ remote: true,
|
|
|
|
+ showQueryButon: true,
|
|
|
|
+ showGenerateButton: true
|
|
}
|
|
}
|
|
)
|
|
)
|
|
-const emits = defineEmits<{ (e: "update:modelValue", v: string): void }>()
|
|
|
|
|
|
+const emits = defineEmits(["querySuccess", "generateSuccess"])
|
|
|
|
+const loading = ref(false)
|
|
|
|
+const title = ref(props.title)
|
|
|
|
+const formData = ref({
|
|
|
|
+ year: new Date().getFullYear(),
|
|
|
|
+ quarter: Math.floor(new Date().getMonth() / 3) + 1,
|
|
|
|
+ month: new Date().getMonth() + 1,
|
|
|
|
+ day: new Date().getDate(),
|
|
|
|
+ reportType: props.reportType,
|
|
|
|
+ reportDateType: props.reportDateType
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const yearOptions = computed(() => {
|
|
|
|
+ const options = []
|
|
|
|
+ for (let i = 2024; i <= new Date().getFullYear(); i++) {
|
|
|
|
+ options.push({
|
|
|
|
+ label: i + "年",
|
|
|
|
+ value: i
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ return options
|
|
|
|
+})
|
|
|
|
+const quarterOptions = computed(() => {
|
|
|
|
+ const options = []
|
|
|
|
+ for (let i = 1; i <= 4; i++) {
|
|
|
|
+ options.push({
|
|
|
|
+ label: `第${i}季度`,
|
|
|
|
+ value: i
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ return options
|
|
|
|
+})
|
|
|
|
+const monthOptions = computed(() => {
|
|
|
|
+ const options = []
|
|
|
|
+ for (let i = 1; i <= 12; i++) {
|
|
|
|
+ options.push({
|
|
|
|
+ label: i + "月",
|
|
|
|
+ value: i
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ return options
|
|
|
|
+})
|
|
|
|
+const dayOptions = computed(() => {
|
|
|
|
+ const options = []
|
|
|
|
+ // 计算每月天数的函数
|
|
|
|
+ const getDaysInMonth = (year: number, month: number) => {
|
|
|
|
+ // 月份索引从0开始,所以需要减1
|
|
|
|
+ return new Date(year, month, 0).getDate()
|
|
|
|
+ }
|
|
|
|
+ const daysInMonth = getDaysInMonth(formData.value.year, formData.value.month)
|
|
|
|
+ for (let i = 1; i <= daysInMonth; i++) {
|
|
|
|
+ options.push({
|
|
|
|
+ label: i + "日",
|
|
|
|
+ value: i
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ return options
|
|
|
|
+})
|
|
|
|
+
|
|
const dateTypeStr = computed(() => {
|
|
const dateTypeStr = computed(() => {
|
|
if (props.reportDateType === "D") {
|
|
if (props.reportDateType === "D") {
|
|
return "日"
|
|
return "日"
|
|
@@ -28,7 +94,15 @@ const dateTypeStr = computed(() => {
|
|
const showEggReport = computed(() => {
|
|
const showEggReport = computed(() => {
|
|
return props.reportType === "EGG"
|
|
return props.reportType === "EGG"
|
|
})
|
|
})
|
|
|
|
+const remoteData = ref({
|
|
|
|
+ data: [],
|
|
|
|
+ totalData: null,
|
|
|
|
+ genDate: props.reportGenDate
|
|
|
|
+})
|
|
const reportData = computed(() => {
|
|
const reportData = computed(() => {
|
|
|
|
+ if (props.remote) {
|
|
|
|
+ return remoteData.value.data
|
|
|
|
+ }
|
|
if (!props.data) {
|
|
if (!props.data) {
|
|
return []
|
|
return []
|
|
}
|
|
}
|
|
@@ -38,6 +112,9 @@ const reportData = computed(() => {
|
|
return props.data
|
|
return props.data
|
|
})
|
|
})
|
|
const totalData = computed(() => {
|
|
const totalData = computed(() => {
|
|
|
|
+ if (props.remote) {
|
|
|
|
+ return remoteData.value.totalData
|
|
|
|
+ }
|
|
if (!props.totalData) {
|
|
if (!props.totalData) {
|
|
return null
|
|
return null
|
|
}
|
|
}
|
|
@@ -46,9 +123,64 @@ const totalData = computed(() => {
|
|
}
|
|
}
|
|
return props.totalData
|
|
return props.totalData
|
|
})
|
|
})
|
|
|
|
+const genDate = computed(() => {
|
|
|
|
+ if (props.remote) {
|
|
|
|
+ return remoteData.value.genDate || props.reportGenDate
|
|
|
|
+ }
|
|
|
|
+ return props.reportGenDate
|
|
|
|
+})
|
|
|
|
+const dataIsEmpty = computed(() => {
|
|
|
|
+ return reportData.value.length === 0
|
|
|
|
+})
|
|
|
|
+function onQueryReport() {
|
|
|
|
+ if (!props.queryReportFun) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ loading.value = true
|
|
|
|
+ props
|
|
|
|
+ .queryReportFun(formData.value)
|
|
|
|
+ .then((res) => {
|
|
|
|
+ remoteData.value = {
|
|
|
|
+ data: res.data,
|
|
|
|
+ totalData: res.totalData,
|
|
|
|
+ genDate: res.genDate
|
|
|
|
+ }
|
|
|
|
+ title.value = res.title
|
|
|
|
+ emits("querySuccess", res, formData.value)
|
|
|
|
+ })
|
|
|
|
+ .catch((err) => {
|
|
|
|
+ console.log(err)
|
|
|
|
+ remoteData.value = {
|
|
|
|
+ data: [],
|
|
|
|
+ totalData: null,
|
|
|
|
+ genDate: null
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .finally(() => {
|
|
|
|
+ loading.value = false
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+function onGenerateReport() {
|
|
|
|
+ if (!props.generateReportFun) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ loading.value = true
|
|
|
|
+ props
|
|
|
|
+ .generateReportFun(formData.value)
|
|
|
|
+ .then(() => {
|
|
|
|
+ onQueryReport()
|
|
|
|
+ emits
|
|
|
|
+ })
|
|
|
|
+ .catch((err) => {
|
|
|
|
+ console.log(err)
|
|
|
|
+ })
|
|
|
|
+ .finally(() => {
|
|
|
|
+ loading.value = false
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
|
|
function init() {
|
|
function init() {
|
|
- //
|
|
|
|
|
|
+ onQueryReport()
|
|
}
|
|
}
|
|
|
|
|
|
onMounted(init)
|
|
onMounted(init)
|
|
@@ -57,12 +189,86 @@ onMounted(init)
|
|
<div class="report-container">
|
|
<div class="report-container">
|
|
<table class="table table-bordered report-table">
|
|
<table class="table table-bordered report-table">
|
|
<thead>
|
|
<thead>
|
|
|
|
+ <tr v-if="remote" style="border: none">
|
|
|
|
+ <th colspan="30" style="border: none">
|
|
|
|
+ <div class="d-flex align-items-center">
|
|
|
|
+ <el-form
|
|
|
|
+ :model="formData"
|
|
|
|
+ label-width="auto"
|
|
|
|
+ :inline="true"
|
|
|
|
+ style="margin-left: 20px">
|
|
|
|
+ <el-form-item label="年">
|
|
|
|
+ <el-select
|
|
|
|
+ v-model="formData.year"
|
|
|
|
+ placeholder="请选择年份"
|
|
|
|
+ style="width: 100px"
|
|
|
|
+ clearable
|
|
|
|
+ @change="formData.month = 1">
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(v, i) in yearOptions"
|
|
|
|
+ :label="v.label"
|
|
|
|
+ :value="v.value"
|
|
|
|
+ :key="i" />
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item v-if="reportDateType === 'Q'" label="季度">
|
|
|
|
+ <el-select
|
|
|
|
+ v-model="formData.quarter"
|
|
|
|
+ style="width: 100px"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="请选择季度">
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(v, i) in quarterOptions"
|
|
|
|
+ :label="v.label"
|
|
|
|
+ :value="v.value"
|
|
|
|
+ :key="i" />
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item v-if="reportDateType === 'M' || reportDateType === 'D'" label="月">
|
|
|
|
+ <el-select
|
|
|
|
+ v-model="formData.month"
|
|
|
|
+ style="width: 80px"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="请选择月份"
|
|
|
|
+ @change="formData.day = 1">
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(v, i) in monthOptions"
|
|
|
|
+ :label="v.label"
|
|
|
|
+ :value="v.value"
|
|
|
|
+ :key="i" />
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item v-if="reportDateType === 'D'" label="日">
|
|
|
|
+ <el-select
|
|
|
|
+ v-model="formData.day"
|
|
|
|
+ style="width: 80px"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="请选择日">
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(v, i) in dayOptions"
|
|
|
|
+ :label="v.label"
|
|
|
|
+ :value="v.value"
|
|
|
|
+ :key="i" />
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item>
|
|
|
|
+ <el-button v-if="showQueryButon" type="primary" @click="onQueryReport">
|
|
|
|
+ 查询报表
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button v-if="showGenerateButton" type="success" @click="onGenerateReport">
|
|
|
|
+ 生成报表
|
|
|
|
+ </el-button>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ </div>
|
|
|
|
+ </th>
|
|
|
|
+ </tr>
|
|
<tr>
|
|
<tr>
|
|
- <th class="report-title" colspan="30">
|
|
|
|
- <span class="report-title-text">
|
|
|
|
|
|
+ <th class="report-header" colspan="30">
|
|
|
|
+ <span class="report-title">
|
|
{{ title }}
|
|
{{ title }}
|
|
</span>
|
|
</span>
|
|
- <span v-if="reportGenDate" class="report-gen-date">生成时间:{{ reportGenDate }}</span>
|
|
|
|
|
|
+ <span v-if="genDate" class="report-gen-date">生成时间:{{ genDate }}</span>
|
|
</th>
|
|
</th>
|
|
</tr>
|
|
</tr>
|
|
<tr>
|
|
<tr>
|
|
@@ -100,7 +306,26 @@ onMounted(init)
|
|
<th class="s-1 s-g">♀</th>
|
|
<th class="s-1 s-g">♀</th>
|
|
</tr>
|
|
</tr>
|
|
</thead>
|
|
</thead>
|
|
- <tbody>
|
|
|
|
|
|
+ <tbody v-if="loading">
|
|
|
|
+ <tr>
|
|
|
|
+ <td colspan="30">
|
|
|
|
+ <span
|
|
|
|
+ class="text-primary h-100px d-flex align-items-center justify-content-center fs-3">
|
|
|
|
+ 正在加载中...
|
|
|
|
+ </span>
|
|
|
|
+ </td>
|
|
|
|
+ </tr>
|
|
|
|
+ </tbody>
|
|
|
|
+ <tbody v-else-if="dataIsEmpty">
|
|
|
|
+ <tr>
|
|
|
|
+ <td colspan="30">
|
|
|
|
+ <div class="text-danger h-100px d-flex align-items-center justify-content-center fs-3">
|
|
|
|
+ 无数据
|
|
|
|
+ </div>
|
|
|
|
+ </td>
|
|
|
|
+ </tr>
|
|
|
|
+ </tbody>
|
|
|
|
+ <tbody v-else>
|
|
<template v-for="(data, index) in reportData" :key="index">
|
|
<template v-for="(data, index) in reportData" :key="index">
|
|
<tr v-for="(item, index2) in data.data" :key="index2">
|
|
<tr v-for="(item, index2) in data.data" :key="index2">
|
|
<td v-if="index2 === 0" class="s-1 s-js" :rowspan="data.data.length">
|
|
<td v-if="index2 === 0" class="s-1 s-js" :rowspan="data.data.length">
|
|
@@ -188,11 +413,23 @@ onMounted(init)
|
|
padding: 10px;
|
|
padding: 10px;
|
|
margin: 0;
|
|
margin: 0;
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
- .report-title {
|
|
|
|
|
|
+ .report-header {
|
|
text-align: center;
|
|
text-align: center;
|
|
position: relative;
|
|
position: relative;
|
|
padding: 0;
|
|
padding: 0;
|
|
- .report-title-text {
|
|
|
|
|
|
+ .report-btn {
|
|
|
|
+ height: 100%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 15px;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ .icon {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ margin-right: 15px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .report-title {
|
|
font-size: 18px;
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
font-weight: bold;
|
|
line-height: 40px;
|
|
line-height: 40px;
|