浏览代码

Update 组件支持远程拉取数据

Yue 2 周之前
父节点
当前提交
4bc1984410
共有 2 个文件被更改,包括 329 次插入31 次删除
  1. 246 9
      UI/VB.VUE/src/components/reports/ChickenCoopReport.vue
  2. 83 22
      UI/VB.VUE/src/views/report/chicken.vue

+ 246 - 9
UI/VB.VUE/src/components/reports/ChickenCoopReport.vue

@@ -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;

+ 83 - 22
UI/VB.VUE/src/views/report/chicken.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import ChickenCoopReport from "@@@/reports/ChickenCoopReport.vue"
 import ChickenCoopReport from "@@@/reports/ChickenCoopReport.vue"
+import dayjs from "dayjs"
 
 
 const data = ref([
 const data = ref([
 	{
 	{
@@ -12,7 +13,7 @@ const data = ref([
 				last_save_1: 34,
 				last_save_1: 34,
 				save_0: 34,
 				save_0: 34,
 				save_1: 34,
 				save_1: 34,
-				cull_0: 12,
+				cull_0: 0,
 				cull_1: 3,
 				cull_1: 3,
 				in_0: 43,
 				in_0: 43,
 				in_1: 5,
 				in_1: 5,
@@ -180,25 +181,85 @@ const data = ref([
 		}
 		}
 	}
 	}
 ])
 ])
-const totalData = ref({
-	last_save_0: 34,
-	last_save_1: 34,
-	save_0: 34,
-	save_1: 34,
-	cull_0: 4,
-	cull_1: 6,
-	in_0: 7,
-	in_1: 7,
-	out_0: 7,
-	out_1: 7,
-	qualified_egg: 90,
-	deformed_egg: 3,
-	break_egg: 2,
-	egg_production_rate: 0.45,
-	egg_pass_rate: 0.9,
-	cull_rate: 0.1,
-	life_rate: 0.9
+
+const totalData = computed(() => {
+	const result = {
+		last_save_0: 0,
+		last_save_1: 0,
+		save_0: 0,
+		save_1: 0,
+		cull_0: 0,
+		cull_1: 0,
+		in_0: 0,
+		in_1: 0,
+		out_0: 0,
+		out_1: 0,
+		qualified_egg: 0,
+		deformed_egg: 0,
+		break_egg: 0,
+		egg_production_rate: 0,
+		egg_pass_rate: 0,
+		cull_rate: 0,
+		life_rate: 0
+	}
+
+	// 遍历每个鸡舍的数据
+	data.value.forEach((coop) => {
+		// 累加每个鸡舍的total数据到总合计中
+		result.last_save_0 += coop.total.last_save_0 || 0
+		result.last_save_1 += coop.total.last_save_1 || 0
+		result.save_0 += coop.total.save_0 || 0
+		result.save_1 += coop.total.save_1 || 0
+		result.cull_0 += coop.total.cull_0 || 0
+		result.cull_1 += coop.total.cull_1 || 0
+		result.in_0 += coop.total.in_0 || 0
+		result.in_1 += coop.total.in_1 || 0
+		result.out_0 += coop.total.out_0 || 0
+		result.out_1 += coop.total.out_1 || 0
+		result.qualified_egg += coop.total.qualified_egg || 0
+		result.deformed_egg += coop.total.deformed_egg || 0
+		result.break_egg += coop.total.break_egg || 0
+
+		// 对于比率字段,需要计算平均值
+		result.egg_production_rate += coop.total.egg_production_rate || 0
+		result.egg_pass_rate += coop.total.egg_pass_rate || 0
+		result.cull_rate += coop.total.cull_rate || 0
+		result.life_rate += coop.total.life_rate || 0
+	})
+
+	// 计算平均比率(如果有鸡舍数据)
+	const coopCount = data.value.length
+	if (coopCount > 0) {
+		result.egg_production_rate = result.egg_production_rate / coopCount
+		result.egg_pass_rate = result.egg_pass_rate / coopCount
+		result.cull_rate = result.cull_rate / coopCount
+		result.life_rate = result.life_rate / coopCount
+	}
+
+	return result
 })
 })
+
+function query(formData) {
+	return new Promise((resolve, reject) => {
+		setTimeout(() => {
+			resolve({
+				data: data.value,
+				totalData: totalData.value,
+				genDate: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+				title: `${formData.year}年 ${formData.month}月份 弥勒育种场(育成舍) 月报表`
+			})
+		}, 1000)
+	})
+}
+
+function gen(formData) {
+	return new Promise((resolve, reject) => {
+		setTimeout(() => {
+			data.value[0].data[0].cull_0 += 1
+			resolve(true)
+		}, 500)
+	})
+}
 </script>
 </script>
 
 
 <template>
 <template>
@@ -207,8 +268,8 @@ const totalData = ref({
 			title="2025年5月份 弥勒育种场(育成舍) 月报表"
 			title="2025年5月份 弥勒育种场(育成舍) 月报表"
 			report-gen-date="2025-08-14 12:39:34"
 			report-gen-date="2025-08-14 12:39:34"
 			report-type="EGG"
 			report-type="EGG"
-			report-date-type="M"
-			:data="data"
-			:total-data="totalData"></ChickenCoopReport>
+			report-date-type="D"
+			:query-report-fun="query"
+			:generate-report-fun="gen"></ChickenCoopReport>
 	</div>
 	</div>
 </template>
 </template>