@@ -4,31 +4,19 @@
< view class = "date-time-wrap" >
< view class = "picker-item" >
< text class = "picker-label" > 餐别 : < / text >
< uni-data-select
v-model = "queryParams.mealType"
:localdata = "range"
@change ="getList"
> < / uni-data-select >
< uni-data-select v-model = "queryParams.mealType" :localdata="range" @change="getList" > < / uni -data -select >
< / view >
<!-- 报餐日期选择 -- >
< view class = "picker-item" >
< text class = "picker-label" > 报餐日期 : < / text >
< uni-datetime-picker
v-model = "queryParams.reportDate"
type = "date"
placeholder = "选择日期"
@change ="onDateConfirm"
class = "picker-input"
> < / uni-datetime-picker >
< uni-datetime-picker v-model = "queryParams.reportDate" type="date" placeholder="选择日期" @change="onDateConfirm"
class = "picker-input" > < / uni-datetime-picker >
< / view >
<!-- 自定义截止时间选择 -- >
< view class = "picker-item" >
< text class = "picker-label" > 截止时间 : < / text >
< view
class = "custom-time-picker"
@click ="openTimePopup"
>
< view class = "custom-time-picker" @click ="openTimePopup" >
< text class = "time-text" > { { formattedDeadlineTime } } < / text >
< uni-icons type = "arrowdown" size = "14" color = "#999" > < / uni-icons >
< / view >
@@ -52,7 +40,7 @@
< text class = "item-label" > 总人数 < / text >
< text class = "item-value" > { { validTotal + invalidTotal } } < / text >
< / view >
<!-- 第二行 -- >
< view class = "stats-item" >
< text class = "item-label" > 有效堂食人数 < / text >
@@ -66,7 +54,7 @@
< text class = "item-label" > 有效总人数 < / text >
< text class = "item-value" > { { validTotal } } < / text >
< / view >
<!-- 第三行 -- >
< view class = "stats-item" >
< text class = "item-label" > 无效堂食人数 < / text >
@@ -94,43 +82,28 @@
< button class = "confirm-btn" @click ="confirmTime" > 确认 < / button >
< / view >
< / view >
< ! - - 时分秒选择区域 - - >
< view class = "time-select-wrap" >
<!-- 小时选择 -- >
< view class = "time-unit" >
< text class = "unit-label" > 时 < / text >
< uni-number-box
v-model = "timeSelect.hour"
:min = "0"
:max = "23"
:step = "1"
@change ="handleTimeChange"
> < / uni-number-box >
< uni-number-box v-model = "timeSelect.hour" :min="0" :max="23" :step="1"
@change ="handleTimeChange" > < / uni -number -box >
< / view >
<!-- 分钟选择 -- >
< view class = "time-unit" >
< text class = "unit-label" > 分 < / text >
< uni-number-box
v-model = "timeSelect.minute"
:min = "0"
:max = "59"
:step = "1"
@change ="handleTimeChange"
> < / uni-number-box >
< uni-number-box v-model = "timeSelect.minute" :min="0" :max="59" :step="1"
@change ="handleTimeChange" > < / uni -number -box >
< / view >
<!-- 秒选择 -- >
< view class = "time-unit" >
< text class = "unit-label" > 秒 < / text >
< uni-number-box
v-model = "timeSelect.second"
:min = "0"
:max = "59"
:step = "1"
@change ="handleTimeChange"
> < / uni-number-box >
< uni-number-box v-model = "timeSelect.second" :min="0" :max="59" :step="1"
@change ="handleTimeChange" > < / uni -number -box >
< / view >
< / view >
< / view >
@@ -139,370 +112,413 @@
< / template >
< script >
import { listMealReport } from "@/api/wms/mealReport" ;
import { getDicts } from '@/api/system/dict/data.js'
import {
listMealReport
} from "@/api/wms/mealReport" ;
import {
getDicts
} from '@/api/system/dict/data.js'
import {
getConfigKey
} from '@/api/system/config.js'
export default {
name : 'MealReportStatistics' ,
data ( ) {
return {
queryParams : {
mealType : '' ,
reportDate : '' ,
pageSize : 9999 ,
pageNum : 1
} ,
deadlineDate : '' , // 截止日期
deadlineTime : '12:00:00' , // 截止时间(原始值)
// 时分秒选择器临时变量
timeSelect : {
hour : 12 ,
minute : 0 ,
second : 0
} ,
list : [ ] ,
loading : false ,
// 统计数据
validDineIn : 0 ,
validTakeout : 0 ,
validTotal : 0 ,
invalidDineIn : 0 ,
invalidTakeout : 0 ,
invalidTotal : 0 ,
range : [ ]
}
} ,
computed : {
// 格式化截止时间显示(补零)
formattedDeadlineTime ( ) {
const [ hour , minute , second ] = this . deadlineTime . split ( ':' ) ;
return ` ${ hour . padStart ( 2 , '0' ) } : ${ minute . padStart ( 2 , '0' ) } : ${ second . padStart ( 2 , '0' ) } ` ;
}
} ,
onLoad ( ) {
// 初始化今日日期
this . initTodayDate ( ) ;
// 初始化截止日期为今日
this . deadlineDate = this . queryParams . reportDate ;
// 获取餐别字典数据
this . getRangeData ( ) ;
// 加载报餐数据
this . getList ( ) ;
} ,
methods : {
/** 初始化今日日期为yyyy-MM-dd格式 */
initTodayDate ( ) {
const today = new Date ( ) ;
const year = today . getFullYear ( ) ;
const month = String ( today . getMonth ( ) + 1 ) . padStart ( 2 , '0' ) ;
const day = String ( today . getDate ( ) ) . padStart ( 2 , '0' ) ;
this . queryParams . reportDate = ` ${ year } - ${ month } - ${ day } ` ;
} ,
/** 获取餐别字典数据 */
getRangeData ( ) {
getDicts ( 'hrm_meal_type' ) . then ( res => {
this . range = res . data . map ( item => ( {
text : item . dictLabel ,
value : item . dictValue
} ) ) ;
} ) ;
} ,
/** 查询部门报餐列表 */
getList ( ) {
this . loading = true ;
listMealReport ( this . queryParams ) . then ( response => {
this . list = response . rows || [ ] ;
this . loading = false ;
this . calcTableSum ( ) ;
} ) . catch ( error => {
console . error ( '获取报餐数据失败:' , error ) ;
this . loading = false ;
} ) ;
} ,
/** 核心逻辑:区分有效/无效报餐统计 */
calcTableSum ( ) {
let validDine = 0 , validTake = 0 , validAll = 0 ;
let invalidDine = 0 , invalidTake = 0 , invalidAll = 0 ;
this . list . forEach ( item => {
// 处理空值,转为数字
const dine = item . dineInPeople ? Number ( item . dineInPeople ) : 0 ;
const take = item . takeoutPeople ? Number ( item . takeoutPeople ) : 0 ;
const total = item . totalPeople ? Number ( item . totalPeople ) : 0 ;
// 判断当前报餐是否有效
if ( this . isValidMealReport ( item . createTime ) ) {
validDine += dine ;
validTake += take ;
validAll += total ;
} else {
invalidDine += dine ;
invalidTake += take ;
invalidAll += total ;
}
} ) ;
// 赋值到统计变量
this . validDineIn = validDine ;
this . validTakeout = validTake ;
this . validTotal = validAll ;
this . invalidDineIn = invalidDine ;
this . invalidTakeout = invalidTake ;
this . invalidTotal = invalidAll ;
} ,
/** 判断报餐是否有效:创建时间在截止时间之前则有效 */
isValidMealReport ( createTime ) {
if ( ! createTime ) return false ;
// 拼接完整的截止时间字符串
const deadlineDateTime = ` ${ this . deadlineDate || this . queryParams . reportDate } ${ this . deadlineTime } ` ;
// 比较时间
const createTimeObj = new Date ( createTime ) ;
const deadlineTimeObj = new Date ( deadlineDateTime ) ;
return createTimeObj <= deadlineTimeObj ;
} ,
/** 报餐日期选择确认 */
onDateConfirm ( e ) {
this . queryParams . reportDate = e ;
// 如果截止日期未选择,同步为报餐日期
if ( ! this . deadlineDate ) {
this . deadlineDate = e ;
export default {
name : 'MealReportStatistics' ,
data ( ) {
return {
queryParams : {
mealType : '' ,
reportDate : '' ,
pageSize : 9999 ,
pageNum : 1
} ,
deadlineDate : '' , // 截止日期
deadlineTime : '12:00:00' , // 截止时间(原始值)
// 时分秒选择器临时变量
timeSelect : {
hour : 12 ,
minute : 0 ,
second : 0
} ,
list : [ ] ,
loading : false ,
// 统计数据
validDineIn : 0 ,
validTakeout : 0 ,
validTotal : 0 ,
invalidDineIn : 0 ,
invalidTakeout : 0 ,
invalidTotal : 0 ,
range : [ ]
}
this . getList ( ) ;
} ,
/** 截止日期选择确认 */
onDeadlineDateConfirm ( e ) {
this . deadlineDate = e ;
this . calcTableSum ( ) ;
computed : {
// 格式化截止时间显示(补零)
formattedDeadlineTime ( ) {
const [ hour , minute , second ] = this . deadlineTime . split ( ':' ) ;
return ` ${ hour . padStart ( 2 , '0' ) } : ${ minute . padStart ( 2 , '0' ) } : ${ second . padStart ( 2 , '0' ) } ` ;
}
} ,
// ===== 自定义时间选择器逻辑 =====
/** 打开时间选择弹窗 */
openTimePopup ( ) {
// 解析当前时间到选择器
const [ hour , minute , second ] = this . deadlineTime . split ( ':' ) . map ( Number ) ;
this . timeSelect = { hour , minute , second } ;
// 打开弹窗
this . $refs . timePopup . open ( 'center' ) ;
onLoad ( ) {
// 初始化今日日期
this . initTodayDate ( ) ;
// 初始化截止日期为今日
this . deadlineDate = this . queryParams . reportDate ;
// 获取餐别字典数据
this . getRangeData ( ) ;
// 加载报餐数据
this . getList ( ) ;
this . getDeadlineConfig ( ) ;
} ,
/** 关闭时间选择弹窗 */
closeTimePopup ( ) {
this . $refs . timePopup . clos e( ) ;
} ,
/** 处理时分秒数值变化 */
handleTimeChange ( ) {
// 确保数值在合法范围内
this . timeSelect . hour = Math . max ( 0 , Math . min ( 23 , this . timeSelect . hour ) ) ;
this . timeSelect . minute = Math . max ( 0 , Math . min ( 59 , this . timeSelect . minute ) ) ;
this . timeSelect . second = Math . max ( 0 , Math . min ( 59 , this . timeSelect . second ) ) ;
} ,
/** 确认选择的时间 */
confirmTime ( ) {
// 格式化时分秒(补零)
const hour = String ( this . timeSelect . hour ) . padStart ( 2 , '0' ) ;
const minute = String ( this . timeSelect . minute ) . padStart ( 2 , '0' ) ;
const second = String ( this . timeSelect . second ) . padStart ( 2 , '0' ) ;
// 更新截止时间
this . deadlineTime = ` ${ hour } : ${ minute } : ${ second } ` ;
// 重新计算统计数据
this . calcTableSum ( ) ;
// 关闭弹窗
this . closeTimePopup ( ) ;
methods : {
/** 初始化今日日期为yyyy-MM-dd格式 */
initTodayDate ( ) {
const today = new Dat e ( ) ;
const year = today . getFullYear ( ) ;
const month = String ( today . getMonth ( ) + 1 ) . padStart ( 2 , '0' ) ;
const day = String ( today . getDate ( ) ) . padStart ( 2 , '0' ) ;
this . queryParams . reportDate = ` ${ year } - ${ month } - ${ day } ` ;
} ,
getDeadlineConfig ( ) {
getConfigKey ( 'hrm.meal.deadline' ) . then ( response => {
this . queryParams . deadlineTime = response . msg || '16:00:00'
} )
} ,
/** 获取餐别字典数据 */
getRangeData ( ) {
getDicts ( 'hrm_meal_type' ) . then ( res => {
this . range = res . data . map ( item => ( {
text : item . dictLabel ,
value : item . dictValue
} ) ) ;
} ) ;
} ,
/** 查询部门报餐列表 */
getList ( ) {
this . loading = true ;
listMealReport ( this . queryParams ) . then ( response => {
this . list = response . rows || [ ] ;
this . loading = false ;
this . calcTableSum ( ) ;
} ) . catch ( error => {
console . error ( '获取报餐数据失败:' , error ) ;
this . loading = false ;
} ) ;
} ,
/** 核心逻辑:区分有效/无效报餐统计 */
calcTableSum ( ) {
let validDine = 0 ,
validTake = 0 ,
validAll = 0 ;
let invalidDine = 0 ,
invalidTake = 0 ,
invalidAll = 0 ;
this . list . forEach ( item => {
// 处理空值,转为数字
const dine = item . dineInPeople ? Number ( item . dineInPeople ) : 0 ;
const take = item . takeoutPeople ? Number ( item . takeoutPeople ) : 0 ;
const total = item . totalPeople ? Number ( item . totalPeople ) : 0 ;
// 判断当前报餐是否有效
if ( this . isValidMealReport ( item . createTime ) ) {
validDine += dine ;
validTake += take ;
validAll += total ;
} else {
invalidDine += dine ;
invalidTake += take ;
invalidAll += total ;
}
} ) ;
// 赋值到统计变量
this . validDineIn = validDine ;
this . validTakeout = validTake ;
this . validTotal = validAll ;
this . invalidDineIn = invalidDine ;
this . invalidTakeout = invalidTake ;
this . invalidTotal = invalidAll ;
} ,
/** 判断报餐是否有效:创建时间在截止时间之前则有效 */
isValidMealReport ( createTime ) {
if ( ! createTime ) return false ;
// 拼接完整的截止时间字符串
const deadlineDateTime = ` ${ this . deadlineDate || this . queryParams . reportDate } ${ this . deadlineTime } ` ;
// 比较时间
const createTimeObj = new Date ( createTime ) ;
const deadlineTimeObj = new Date ( deadlineDateTime ) ;
return createTimeObj <= deadlineTimeObj ;
} ,
/** 报餐日期选择确认 */
onDateConfirm ( e ) {
this . queryParams . reportDate = e ;
// 如果截止日期未选择,同步为报餐日期
if ( ! this . deadlineDate ) {
this . deadlineDate = e ;
}
this . getList ( ) ;
} ,
/** 截止日期选择确认 */
onDeadlineDateConfirm ( e ) {
this . deadlineDate = e ;
this . calcTableSum ( ) ;
} ,
// ===== 自定义时间选择器逻辑 =====
/** 打开时间选择弹窗 */
openTimePopup ( ) {
// 解析当前时间到选择器
const [ hour , minute , second ] = this . deadlineTime . split ( ':' ) . map ( Number ) ;
this . timeSelect = {
hour ,
minute ,
second
} ;
// 打开弹窗
this . $refs . timePopup . open ( 'center' ) ;
} ,
/** 关闭时间选择弹窗 */
closeTimePopup ( ) {
this . $refs . timePopup . close ( ) ;
} ,
/** 处理时分秒数值变化 */
handleTimeChange ( ) {
// 确保数值在合法范围内
this . timeSelect . hour = Math . max ( 0 , Math . min ( 23 , this . timeSelect . hour ) ) ;
this . timeSelect . minute = Math . max ( 0 , Math . min ( 59 , this . timeSelect . minute ) ) ;
this . timeSelect . second = Math . max ( 0 , Math . min ( 59 , this . timeSelect . second ) ) ;
} ,
/** 确认选择的时间 */
confirmTime ( ) {
// 格式化时分秒(补零)
const hour = String ( this . timeSelect . hour ) . padStart ( 2 , '0' ) ;
const minute = String ( this . timeSelect . minute ) . padStart ( 2 , '0' ) ;
const second = String ( this . timeSelect . second ) . padStart ( 2 , '0' ) ;
// 更新截止时间
this . deadlineTime = ` ${ hour } : ${ minute } : ${ second } ` ;
// 重新计算统计数据
this . calcTableSum ( ) ;
// 关闭弹窗
this . closeTimePopup ( ) ;
}
}
}
}
< / script >
< style scoped >
/* 容器样式 */
. meal - report - container {
padding : 15 px ;
background - color : # f5f5f5 ;
min - height : 100 vh ;
}
/* 容器样式 */
. meal - report - container {
padding : 15 px ;
background - color : # f5f5f5 ;
min - height : 100 vh ;
}
/* 日期时间选择区域 */
. date - time - wrap {
display : flex ;
flex - direction : column ;
gap : 10 px ;
margin - bottom : 20 px ;
background - color : # fff ;
padding : 15 px ;
border - radius : 8 px ;
}
. picker - item {
display : flex ;
align - items : center ;
gap : 8 px ;
}
. picker - label {
font - size : 14 px ;
color : # 333 ;
min - width : 80 px ;
}
. picker - input {
flex : 1 ;
}
/* 日期时间选择区域 */
. date - time - wrap {
display : flex ;
flex - direction : column ;
gap : 10 px ;
margin - bottom : 20 px ;
background - color : # fff ;
padding : 15 px ;
border - radius : 8 px ;
}
/* 自定义时间选择器样式 */
. custom - time - picker {
flex : 1 ;
display : fle x;
align - items : center ;
justify - content : space - between ;
padding : 8 px 10 px ;
border : 1 px solid # eee ;
border - radius : 4 px ;
background - color : # fff ;
}
. time - text {
font - size : 14 px ;
color : # 333 ;
}
. picker - item {
display : flex ;
align - items : center ;
gap : 8 p x;
}
/* 统计卡片样式 */
. statistics - card {
background - color : # fff ;
border - radius : 8 px ;
overflow : hidden ;
box - shadow : 0 2 px 8 px rgba ( 0 , 0 , 0 , 0.05 ) ;
}
. card - title {
font - size : 16 px ;
font - weight : 600 ;
color : # 333 ;
padding : 12 px 15 px ;
border - bottom : 1 px solid # eee ;
}
. picker - label {
font - size : 14 px ;
color : # 333 ;
min - width : 80 px ;
}
/* 网格布局: 3列 */
. stats - grid {
display : grid ;
grid - template - columns : repeat ( 3 , 1 fr ) ;
border : 1 px solid # eee ;
border - top : none ;
}
. picker - input {
flex : 1 ;
}
/* 统计项 样式 */
. stats - item {
padding : 12 px 8 px ;
text - align : center ;
border - right : 1 px solid # eee ;
border - bottom : 1 px solid # e ee;
box - sizing : border - bo x;
font - size : 14 px ;
}
/* 去掉最后一列右边框 */
. stats - grid . stats - item : nth - child ( 3 n ) {
border - right : none ;
}
/* 去掉最后一行下边框 */
. stats - grid . stats - item : last - child ,
. stats - grid . stats - item : nth - last - child ( 2 ) ,
. stats - grid . stats - item : nth - last - child ( 3 ) {
border - bottom : none ;
}
/* 自定义时间选择器 样式 */
. custom - time - picker {
flex : 1 ;
display : flex ;
align - items : center ;
justify - content : space - betw een ;
padding : 8 px 10 p x ;
border : 1 px solid # eee ;
border - radius : 4 px ;
background - color : # fff ;
}
/* 标签和值样式 */
. item - label {
display : block ;
color : # 666 ;
font - size : 12 px ;
margin - bottom : 4 px ;
}
. item - value {
display : block ;
color : # 333 ;
font - size : 15 px ;
font - weight : 500 ;
}
. time - text {
font - size : 14 px ;
color : # 333 ;
}
/* 时间弹窗 样式 */
. time - popup - content {
background - color : # fff ;
padding - bottom : 20 px ;
}
. popup - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
padding : 12 px 15 px ;
border - bottom : 1 px solid # eee ;
}
. popup - title {
font - size : 16 px ;
font - weight : 600 ;
color : # 333 ;
}
. popup - btns {
display : flex ;
gap : 10 px ;
}
. cancel - btn , . confirm - btn {
padding : 6 px 12 px ;
font - size : 14 px ;
border - radius : 4 px ;
}
. cancel - btn {
background - color : # f5f5f5 ;
color : # 666 ;
border : 1 px solid # eee ;
}
. confirm - btn {
background - color : # 007 aff ;
color : # fff ;
border : none ;
}
/* 统计卡片 样式 */
. statistics - card {
background - color : # fff ;
border - radius : 8 px ;
overflow : hidden ;
box - shadow : 0 2 px 8 px rgba ( 0 , 0 , 0 , 0.05 ) ;
}
/* 时分秒选择区域 */
. time - select - wrap {
display : flex ;
flex - direction : column ;
align - items : center ;
justify - content : center ;
gap : 10 px ;
padding : 20 px 15 px ;
}
. time - unit {
display : flex ;
align - items : center ;
gap : 8 px ;
}
. unit - label {
font - size : 12 px ;
color : # 999 ;
}
. colon {
font - size : 20 px ;
color : # 333 ;
margin : 0 5 px ;
}
. card - title {
font - size : 16 px ;
font - weight : 600 ;
color : # 333 ;
padding : 12 px 15 px ;
border - bottom : 1 px solid # eee ;
}
/* 适配小屏手机 */
@ media ( max - width : 375 px ) {
/* 网格布局: 3列 */
. stats - grid {
display : grid ;
grid - template - columns : repeat ( 3 , 1 fr ) ;
border : 1 px solid # eee ;
border - top : none ;
}
/* 统计项样式 */
. stats - item {
padding : 10 px 5 px ;
}
. item - label {
font - size : 11 px ;
}
. item - value {
padding : 12 px 8 px ;
text - align : center ;
border - right : 1 px solid # eee ;
border - bottom : 1 px solid # eee ;
box - sizing : border - box ;
font - size : 14 px ;
}
. time - select - wrap {
gap : 5 px ;
padding : 15 px 10 px ;
/* 去掉最后一列右边框 */
. stats - grid . stats - item : nth - child ( 3 n ) {
border - right : none ;
}
/* 去掉最后一行下边框 */
. stats - grid . stats - item : last - child ,
. stats - grid . stats - item : nth - last - child ( 2 ) ,
. stats - grid . stats - item : nth - last - child ( 3 ) {
border - bottom : none ;
}
/* 标签和值样式 */
. item - label {
display : block ;
color : # 666 ;
font - size : 12 px ;
margin - bottom : 4 px ;
}
. item - value {
display : block ;
color : # 333 ;
font - size : 15 px ;
font - weight : 500 ;
}
/* 时间弹窗样式 */
. time - popup - content {
background - color : # fff ;
padding - bottom : 20 px ;
}
. popup - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
padding : 12 px 15 px ;
border - bottom : 1 px solid # eee ;
}
. popup - title {
font - size : 16 px ;
font - weight : 600 ;
color : # 333 ;
}
. popup - btns {
display : flex ;
gap : 10 px ;
}
. cancel - btn ,
. confirm - btn {
padding : 6 px 12 px ;
font - size : 14 px ;
border - radius : 4 px ;
}
. cancel - btn {
background - color : # f5f5f5 ;
color : # 666 ;
border : 1 px solid # eee ;
}
. confirm - btn {
background - color : # 007 aff ;
color : # fff ;
border : none ;
}
/* 时分秒选择区域 */
. time - select - wrap {
display : flex ;
flex - direction : column ;
align - items : center ;
justify - content : center ;
gap : 10 px ;
padding : 20 px 15 px ;
}
. time - unit {
display : flex ;
align - items : center ;
gap : 8 px ;
}
. unit - label {
font - size : 12 px ;
color : # 999 ;
}
. colon {
font - size : 20 px ;
color : # 333 ;
margin : 0 5 px ;
}
/* 适配小屏手机 */
@ media ( max - width : 375 px ) {
. stats - item {
padding : 10 px 5 px ;
}
. item - label {
font - size : 11 px ;
}
. item - value {
font - size : 14 px ;
}
. time - select - wrap {
gap : 5 px ;
padding : 15 px 10 px ;
}
}
}
< / style >