2025年6月9日10:23:02

This commit is contained in:
17792275749
2025-06-09 10:23:05 +08:00
commit 9df8b7e8e2
146 changed files with 23980 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
import { getRequest } from '@/axios';
let url = {
ct: "/shuwei-zhct/swLargeScreenFood/foodInfoByDeviceId", // 餐厅
st: "/local/zhstapi/zhst/tv/foodInfoByDeviceId", // 食堂
};
export const info = (type, params) => getRequest(type + 'Request', url[type], params);
+384
View File
@@ -0,0 +1,384 @@
<template>
<div id="dishesDetails-info">
<div class="personTime">
<div>取餐人次</div>
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<countTo
:startVal="dishesDetails.num_ ? dishesDetails.num_ : 0"
:endVal="dishesDetails.num"
separator=""
:duration="1500"
@count-to-finish="handleFinish('num')" />
</template>
<template v-else>-</template>
</div>
</div>
<div class="dishesPictures">
<template v-if="dishesDetails && dishesDetails.foodId && dishesDetails.relativeUrl">
<img :src="dishesDetails.relativeUrl" :alt="dishesDetails.relativeUrl" />
</template>
<template v-else>
<img src="@/assets/images/dishesDetails/null.png" />
</template>
</div>
<div class="dishesInfo">
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<div>
<div>{{ dishesDetails.foodName }}</div>
<div :style="{'color': dishesDetails.initialStatus ? '#FF2222' : '#161616'}">
(
<countTo
:startVal="dishesDetails.initial_ ? dishesDetails.initial_ : 0"
:endVal="dishesDetails.initial"
separator=""
:decimals="2"
:duration="1500"
@count-to-finish="handleFinish('initial')" />
)
</div>
</div>
</template>
<template v-else>
<div>
<div style="color: #77849E">暂无数据</div>
</div>
</template>
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<template v-for="item in dishesDetails.itemTexts">
<div>{{ item }}</div>
</template>
</template>
</div>
<div>
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<div>
<countTo
:startVal="dishesDetails.surplus ? dishesDetails.surplus_ : 0"
:endVal="dishesDetails.surplus"
separator=""
:decimals="2"
:duration="1500"
@count-to-finish="handleFinish('surplus')" />
</div>
</template>
<template v-else>
<div style="color: #77849E">-</div>
</template>
<div>余量(kg)</div>
</div>
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<div>
<countTo
:startVal="dishesDetails.eatWeight_ ? dishesDetails.eatWeight_ : 0"
:endVal="dishesDetails.eatWeight"
separator=""
:decimals="2"
:duration="1500"
@count-to-finish="handleFinish('eatWeight')" />
</div>
</template>
<template v-else>
<div style="color: #77849E">-</div>
</template>
<div>实名取餐(kg)</div>
</div>
<div>
<template v-if="dishesDetails && dishesDetails.foodId">
<div :style="{'color': dishesDetails.anonymityWeight > 0 ? '#FF2222' : '#161616'}">
<countTo
:startVal="dishesDetails.anonymityWeight_ ? dishesDetails.anonymityWeight_ : 0"
:endVal="dishesDetails.anonymityWeight"
separator=""
:decimals="2"
:duration="1500"
@count-to-finish="handleFinish('anonymityWeight')" />
</div>
</template>
<template v-else>
<div style="color: #77849E">-</div>
</template>
<div>丢失餐量(kg)</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import countTo from "vue-count-to";
import {initMqtt, callBackMqttMessage} from "@/utils/mqtt";
import {info} from "../api";
export default {
name: "info",
props: {
type: {
type: String,
required: true,
},
keyName: {
type: String,
required: true,
},
},
components: {
countTo
},
data() {
return {
deviceId: "",
dishesDetails: null
}
},
created() {
let deviceId = this.$route.query[this.keyName];
if(deviceId) {
this.deviceId = deviceId;
initMqtt('deviceId-' + Math.random().toString(16).substring(2, 8), "sw_device_msg", this.type).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
this.loadData(deviceId);
}
},
methods: {
loadData(deviceId) {
if(deviceId === this.deviceId) {
let params = {
deviceId: deviceId
};
info(this.type, params).then(res => {
if (res.success) {
let data = this.type === 'ct' ? res.data : res.result;
data.initialStatus = this.isAOutOf10PercentOfB(data);
this.dishesDetails = data;
}
});
}
},
isAOutOf10PercentOfB(data) {
let initial = Number((data.surplus + data.eatWeight + data.anonymityWeight).toFixed(2));
let lowerBound = data.initial * 0.9;
let upperBound = data.initial * 1.1;
return initial <= lowerBound || initial >= upperBound;
},
handleFinish(k) {
let newKey = k + '_';
this.dishesDetails[newKey] = this.dishesDetails[k];
},
mqttMessage(data) {
this.loadData(data.deviceId);
}
},
mounted() {
callBackMqttMessage((data) => {
this.mqttMessage(data.message);
});
}
}
</script>
<style scoped lang="less">
#dishesDetails-info {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
border-radius: 24px;
background-color: #FFFFFF;
.personTime {
position: absolute;
z-index: 3;
top: 0;
left: 0;
right: 0;
margin: auto;
width: 500px;
height: 168px;
padding-top: 20px;
box-sizing: border-box;
background-size: cover;
background-position: center top;
background-repeat: no-repeat;
background-image: url("@/assets/images/dishesDetails/personTime.png");
> div:nth-of-type(1) {
color: #FFFFFF;
height: 30px;
font-size: 30px;
line-height: 30px;
text-align: center;
margin-bottom: 16px;
}
> div:nth-of-type(2) {
color: #FFFFFF;
height: 80px;
font-size: 80px;
line-height: 80px;
font-weight: bold;
text-align: center;
}
}
.dishesPictures {
width: 100%;
height: 800px;
position: relative;
img {
width: 100%;
height: 100%;
}
&::before {
content: "";
position: absolute;
z-index: 2;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 400px;
background: linear-gradient(0deg, #FFFFFF 0%, #1B2E54 0%, #FFFFFF 0%, rgba(255,255,255,0) 100%);
}
}
.dishesInfo {
position: absolute;
z-index: 4;
left: 24px;
right: 24px;
bottom: 24px;
margin: auto;
height: 500px;
overflow: hidden;
border-radius: 24px;
box-sizing: border-box;
border: 1px solid #FFFFFF;
> div {
width: 100%;
height: 100%;
padding: 76px 15px 0;
box-sizing: border-box;
position: relative;
> div:nth-of-type(1) {
width: 100%;
height: 64px;
display: flex;
flex-wrap: nowrap;
justify-content: center;
margin-bottom: 45px;
> div:nth-of-type(1) {
color: #161616;
height: 64px;
font-size: 64px;
font-weight: bold;
line-height: 64px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
> div:nth-of-type(2) {
color: #161616;
height: 64px;
font-size: 64px;
font-weight: bold;
line-height: 64px;
white-space: nowrap;
display: flex;
gap: 0;
}
}
> div:nth-of-type(2) {
width: 100%;
height: 64px;
display: flex;
flex-wrap: nowrap;
justify-content: center;
margin-bottom: 70px;
> div {
color: #04A777;
font-size: 30px;
font-weight: bold;
height: 62px;
padding: 0 22px;
line-height: 62px;
border-radius: 6px;
margin: 0 12px;
background-color: #DBF6EE;
border: 1px solid #BCEFE1;
}
}
> div:nth-of-type(3) {
width: 100%;
display: flex;
flex-wrap: nowrap;
> div {
flex: 1;
width: 0;
> div:nth-of-type(1) {
color: #161616;
height: 80px;
font-size: 80px;
line-height: 80px;
font-weight: bold;
text-align: center;
margin-bottom: 40px;
}
> div:nth-of-type(2) {
color: #999999;
height: 30px;
font-size: 30px;
line-height: 30px;
text-align: center;
}
}
}
&:before {
position: absolute;
z-index: -1;
content: "";
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0.67;
background-color: #EEF6FD;
}
}
}
.nullData {
width: 100%;
padding-top: 30vh;
font-size: 36px;
text-align: center;
}
}
</style>
+48
View File
@@ -0,0 +1,48 @@
<template>
<div id="dishesDetails">
<div>
<Info :type="type" keyName="l" />
</div>
<div>
<Info :type="type" keyName="r" />
</div>
</div>
</template>
<script>
import Info from "./components/info.vue";
export default {
name: "dishesDetails",
components: {
Info
},
data() {
return {
type: this.$route.query.type,
}
},
created() {
}
}
</script>
<style scoped lang="less">
#dishesDetails {
width: 100%;
height: 100%;
overflow: hidden;
padding: 48px 107px;
box-sizing: border-box;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
background-color: #000000;
> div {
width: 800px;
height: 100%;
}
}
</style>