396 lines
14 KiB
Vue
396 lines
14 KiB
Vue
<template>
|
||
<div v-loading="loading" class="layout-padding">
|
||
<div class="layout-padding-auto layout-padding-view" style="overflow: scroll !important">
|
||
<el-descriptions :column="3" title="经营信息" border>
|
||
<template #extra>
|
||
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
||
<el-button circle icon="Refresh" @click="doRefresh" />
|
||
</el-tooltip>
|
||
</template>
|
||
<el-descriptions-item label="今日交易金额:">{{ displayPrice(0) }}</el-descriptions-item>
|
||
<el-descriptions-item label="本月交易金额:">{{ displayPrice(0) }}</el-descriptions-item>
|
||
<el-descriptions-item label="本年交易金额:">{{ displayPrice(0) }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<el-descriptions :column="3" title="智能柜设置" border>
|
||
<template #extra>
|
||
<el-button icon="Edit" type="primary" @click="changeInfo">修改</el-button>
|
||
</template>
|
||
<el-descriptions-item label="商户名称:">{{}}</el-descriptions-item>
|
||
<el-descriptions-item label="设备编号:">{{ state.deviceDetail.deviceCode }}</el-descriptions-item>
|
||
<el-descriptions-item label="设备名称:">{{ state.deviceDetail.hardName }}</el-descriptions-item>
|
||
<el-descriptions-item label="设备IMEI卡号:">{{ state.deviceDetail.imei }}</el-descriptions-item>
|
||
<el-descriptions-item label="货柜数量:">{{ state.deviceDetail.cabinetNum }}</el-descriptions-item>
|
||
<el-descriptions-item label="单个货柜摄像头数量:">{{ state.deviceDetail.cabinetCameraNum }}</el-descriptions-item>
|
||
<el-descriptions-item label="单个货柜称重单元数量:">{{ state.deviceDetail.cabinetWeightUnitNum }}</el-descriptions-item>
|
||
<el-descriptions-item label="SIM卡号:">{{ state.deviceDetail.simSn }}</el-descriptions-item>
|
||
<el-descriptions-item label="柜子层数:">{{ state.deviceDetail.doorCount }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<el-descriptions :column="3" title="运行信息" border>
|
||
<template #extra>
|
||
<el-button icon="Edit" type="primary" @click="doVolumeSetting">音量设置</el-button>
|
||
</template>
|
||
<el-descriptions-item label="售卖状态:">
|
||
<el-tag v-if="state.deviceDetail.saleStatus == 1" type="primary">在售</el-tag>
|
||
<el-tag v-if="state.deviceDetail.saleStatus == 2" type="danger">停售</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="电源状态:">
|
||
<el-tag v-if="state.deviceDetail.powerStatus == 1" type="primary">通电</el-tag>
|
||
<el-tag v-if="state.deviceDetail.powerStatus == 2" type="danger">断电</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="在线状态:">
|
||
<el-tag v-if="state.deviceDetail.netStatus == 1" type="primary">在线</el-tag>
|
||
<el-tag v-if="state.deviceDetail.netStatus == 2" type="danger">离线</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="媒体音量:">
|
||
<div class="color-danger">{{ state.deviceDetail.mediaVolume }}</div>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="系统音量:">
|
||
<div class="color-danger">{{ state.deviceDetail.systemVolume }}</div>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item>
|
||
{{ state.deviceDetail.signalIntensity }}
|
||
<template #label>
|
||
SIM信号强度<tip content="大于 -95 表示信号强度好;-95 到 -105 表示信号强度中等;小于 -105 表示信号差" />:
|
||
</template>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item>
|
||
{{ state.deviceDetail.signalRatio }}
|
||
<template #label>
|
||
信噪比<tip content="用于体现信道传输质量的参数。大于 15 表示质量好;15 到 0 表示质量中等;小于等于 0 表示质量差" />:
|
||
</template>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="SIM信号值更新时间:">{{ state.deviceDetail.signalTime }}</el-descriptions-item>
|
||
<el-descriptions-item label="上次重启时间:">{{ state.deviceDetail.restartTime }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<el-descriptions :column="3" title="货柜信息" border>
|
||
<template #extra>
|
||
<el-space>
|
||
<el-button icon="CircleCheck" type="primary" @click="checkOpenAccess" :disabled="checkCloseLoading" :loading="checkOpenLoading">
|
||
检修开门
|
||
</el-button>
|
||
<el-button
|
||
icon="CircleClose"
|
||
type="primary"
|
||
@click="checkCloseAccess"
|
||
:disabled="checkOpenLoading"
|
||
:loading="checkCloseLoading"
|
||
>
|
||
检修关门
|
||
</el-button>
|
||
</el-space>
|
||
</template>
|
||
</el-descriptions>
|
||
<el-tabs type="border-card" @tab-click="doorTabClick">
|
||
<el-tab-pane
|
||
v-if="state.deviceDetail.cabinetList?.length"
|
||
:label="state.deviceDetail.deviceCode + '-' + item.cabinetNo"
|
||
v-for="(item, index) in state.deviceDetail.cabinetList"
|
||
:key="index"
|
||
>
|
||
<el-descriptions :column="3" title="" border>
|
||
<el-descriptions-item label="货柜号:">{{ item.cabinetNo }}</el-descriptions-item>
|
||
<el-descriptions-item label="锁在线:">
|
||
<el-tag v-if="item.isLockOnline == 'Y'" type="primary">在线</el-tag>
|
||
<el-tag v-if="item.isLockOnline == 2" type="primary">离线</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="锁状态:">
|
||
<el-tag v-if="item.lockStatus == 1" type="primary">锁关</el-tag>
|
||
<el-tag v-if="item.lockStatus == 2" type="danger">锁开</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="门状态:">
|
||
<el-tag v-if="item.doorStatus == 1" type="primary">门关</el-tag>
|
||
<el-tag v-if="item.doorStatus == 2" type="danger">门开</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="货柜售卖状态:">
|
||
<el-tag v-if="item.saleStatus == 1" type="primary">在售</el-tag>
|
||
<el-tag v-if="item.saleStatus == 2" type="danger">停售</el-tag>
|
||
</el-descriptions-item>
|
||
</el-descriptions>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
|
||
<el-descriptions :column="0" title="货柜商品" border>
|
||
<!-- <template #extra>
|
||
<el-button icon="Edit" type="primary">设置</el-button>
|
||
</template> -->
|
||
</el-descriptions>
|
||
|
||
<el-tabs type="border-card" @tab-click="tabClick">
|
||
<el-tab-pane
|
||
v-if="state.deviceDetail.cabinetList?.length"
|
||
:label="state.deviceDetail.deviceCode + '-' + item.cabinetNo"
|
||
v-for="(item, index) in state.deviceDetail.cabinetList"
|
||
:key="index"
|
||
>
|
||
<div v-for="(floorItem, floorIndex) in state.cabinetData" :key="floorIndex">
|
||
<el-divider />
|
||
<div class="text-black flex items-center">
|
||
<div class="text-center w-24 text-lg font-bold">第 {{ floorIndex + 1 }} 层:</div>
|
||
<div class="flex flex-wrap">
|
||
<div class="flex flex-col items-center justify-start" v-for="(v, indexNo) in floorItem[floorIndex + 1]" :key="indexNo">
|
||
<div v-if="v.spuId && v.spuDetail" class="w-20 mx-4 my-1 flex flex-col items-center">
|
||
<div class="relative">
|
||
<el-icon @click.stop="deleteGoods(v)" class="absolute right-[-8px] top-[-8px] text-xl text-blue-600 z-50">
|
||
<CircleClose />
|
||
</el-icon>
|
||
<preview-image width="86px" height="86px" :src="v.spuDetail.pic" @click.stop />
|
||
</div>
|
||
<el-tooltip effect="dark" :content="v.spuDetail?.name">
|
||
<div class="line-clamp-1">{{ v.spuDetail?.name }}</div>
|
||
</el-tooltip>
|
||
<div
|
||
class="color-primary w-full flex items-center"
|
||
:class="v.spuDetail.specsCapacity ? 'justify-between' : 'justify-center'"
|
||
>
|
||
<span>{{ displayPrice(v.spuDetail.price) }}</span>
|
||
<span>{{ v.spuDetail.specsCapacity }}</span>
|
||
</div>
|
||
<!-- <div class="w-full flex items-center justify-between">
|
||
<span>{{ v.spuDetail.specsTaste }}</span>
|
||
<span>{{ v.spuDetail.specsWeight }}</span>
|
||
<span>{{ v.spuDetail.categoryName }}</span>
|
||
</div> -->
|
||
</div>
|
||
<div
|
||
v-else
|
||
class="bg-blue-50 w-20 h-20 border border-black mx-4 my-1 flex items-center justify-center cursor-pointer rounded-lg"
|
||
@click="clickPutaway(v.id)"
|
||
>
|
||
点击上架
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
|
||
<!-- 柜子设置 -->
|
||
<info-setting ref="infoSettingRef" @refreshInfo="refreshInfo" />
|
||
|
||
<!-- 音量设置 -->
|
||
<volume-setting ref="volumeSettingRef" @refreshVolume="refreshVolume" />
|
||
|
||
<!-- 商品上架 -->
|
||
<goods-putaway ref="goodsPutawayRef" @refreshCabinet="refreshCabinet" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts" name="hardDoorManager">
|
||
import { onMounted, ref } from "vue"
|
||
import { useMessage } from "/@/hooks/message"
|
||
import { displayPrice } from "/@/utils/formatMoney"
|
||
import * as hardDoorManager from "/@/api/hard/hard-door-manager"
|
||
import { ElMessageBox } from "element-plus"
|
||
import { getByCabinetNo, unPutaway } from "/@/api/hard/hard-spu"
|
||
import { closeAccess, openAccess } from "/@/api/hard/hard-door-manager"
|
||
|
||
const InfoSetting = defineAsyncComponent(() => import("./info-setting.vue"))
|
||
const VolumeSetting = defineAsyncComponent(() => import("./volume-setting.vue"))
|
||
const GoodsPutaway = defineAsyncComponent(() => import("./goods-putaway.vue"))
|
||
|
||
const { query } = useRoute()
|
||
const loading = ref(false)
|
||
const checkOpenLoading = ref(false)
|
||
const checkCloseLoading = ref(false)
|
||
const infoSettingRef = ref()
|
||
const volumeSettingRef = ref()
|
||
const goodsPutawayRef = ref()
|
||
const state = reactive<any>({
|
||
hardId: "",
|
||
deviceDetail: {},
|
||
cabinetData: [],
|
||
curActivedDoorTabIndex: 0,
|
||
curActivedTabIndex: 0,
|
||
})
|
||
|
||
onMounted(async () => {
|
||
await getDetail()
|
||
await getCabinet()
|
||
})
|
||
|
||
// 获取柜子详情
|
||
const getDetail = async () => {
|
||
const id = query.id as unknown as any
|
||
if (!id) return useMessage().error("设备id不存在")
|
||
state.hardId = id
|
||
const { data } = await hardDoorManager.getByHardId({ hardId: state.hardId })
|
||
if (data) {
|
||
state.deviceDetail = { ...data, cabinetList: JSON.parse(data.cabinetList) }
|
||
}
|
||
}
|
||
|
||
// 获取柜子物品
|
||
const getCabinet = async (cabinetIndex: number = 0) => {
|
||
if (!state.hardId) return useMessage().error("设备id不存在")
|
||
if (!state.deviceDetail.cabinetList?.length) return useMessage().error("设备空间不存在")
|
||
const { data } = await getByCabinetNo({
|
||
hardId: state.hardId,
|
||
cabinetNo: state.deviceDetail.cabinetList[cabinetIndex].cabinetNo,
|
||
})
|
||
if (data) {
|
||
state.cabinetData = data
|
||
}
|
||
}
|
||
|
||
// 修改基本信息
|
||
const changeInfo = async () => {
|
||
if (infoSettingRef.value) {
|
||
infoSettingRef.value.openDialog(state.hardId)
|
||
}
|
||
}
|
||
const refreshInfo = () => {
|
||
doRefresh()
|
||
}
|
||
|
||
// 音量设置
|
||
const doVolumeSetting = async () => {
|
||
if (volumeSettingRef.value) {
|
||
volumeSettingRef.value.openDialog(state.deviceDetail.hardId, state.deviceDetail.mediaVolume, state.deviceDetail.systemVolume)
|
||
}
|
||
}
|
||
const refreshVolume = (data: { hardId: string; mediaVolume: number; systemVolume: number }) => {
|
||
state.deviceDetail.mediaVolume = data.mediaVolume
|
||
state.deviceDetail.systemVolume = data.systemVolume
|
||
}
|
||
|
||
// 检修开门
|
||
const checkOpenAccess = async () => {
|
||
try {
|
||
checkOpenLoading.value = true
|
||
const res = await openAccess({
|
||
hardDoorId: state.hardId,
|
||
cabinetNo: state.deviceDetail.cabinetList[state.curActivedDoorTabIndex].cabinetNo,
|
||
})
|
||
if (res.code == 0) {
|
||
useMessage().success("操作成功")
|
||
return
|
||
}
|
||
useMessage().error(res.msg || "操作失败")
|
||
} catch (error: any) {
|
||
useMessage().error(error.msg)
|
||
} finally {
|
||
checkOpenLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 检修关门
|
||
const checkCloseAccess = async () => {
|
||
try {
|
||
checkCloseLoading.value = true
|
||
const res = await closeAccess({
|
||
hardDoorId: state.hardId,
|
||
cabinetNo: state.deviceDetail.cabinetList[state.curActivedDoorTabIndex].cabinetNo,
|
||
})
|
||
if (res.code == 0) {
|
||
useMessage().success("操作成功")
|
||
return
|
||
}
|
||
useMessage().error(res.msg || "操作失败")
|
||
} catch (error: any) {
|
||
useMessage().error(error.msg)
|
||
} finally {
|
||
checkCloseLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 点击柜门tab
|
||
const doorTabClick = async (tab: any) => {
|
||
state.curActivedDoorTabIndex = tab.index
|
||
}
|
||
|
||
// 点击柜门商品tab
|
||
const tabClick = async (tab: any) => {
|
||
state.curActivedTabIndex = tab.index
|
||
await getCabinet(tab.index)
|
||
}
|
||
|
||
// 点击上架
|
||
const clickPutaway = (cabinetItemId: any) => {
|
||
if (goodsPutawayRef.value) {
|
||
goodsPutawayRef.value.openDialog(cabinetItemId)
|
||
}
|
||
}
|
||
const refreshCabinet = async () => {
|
||
try {
|
||
loading.value = true
|
||
await getCabinet(state.curActivedTabIndex)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const doRefresh = async () => {
|
||
try {
|
||
loading.value = true
|
||
await getDetail()
|
||
await getCabinet(state.curActivedTabIndex)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 下架商品
|
||
const deleteGoods = async (v: any) => {
|
||
if (!v.id) return useMessage().error("绑定id不存在")
|
||
if (!v.spuId) return useMessage().error("商品id不存在")
|
||
ElMessageBox.confirm("确定下架吗?", "商品下架", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(
|
||
async () => {
|
||
loading.value = true
|
||
const res = await unPutaway({ id: v.id, hardSpuId: v.spuId }).finally(() => (loading.value = false))
|
||
if (res.code == 0) {
|
||
useMessage().success("下架成功")
|
||
return getCabinet(state.curActivedTabIndex)
|
||
}
|
||
useMessage().error(res.msg || "下架失败")
|
||
},
|
||
)
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
:deep(.el-descriptions) {
|
||
&:not(:nth-child(1)) {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.el-descriptions__cell.is-bordered-label {
|
||
width: 150px;
|
||
background-color: transparent;
|
||
border: none;
|
||
}
|
||
|
||
.el-descriptions__cell.is-bordered-content {
|
||
width: 200px;
|
||
border: none;
|
||
}
|
||
|
||
.el-descriptions__title {
|
||
display: flex;
|
||
align-items: center;
|
||
&::before {
|
||
display: inline-block;
|
||
width: 3px;
|
||
height: 20px;
|
||
margin-right: 10px;
|
||
background-color: #409eff;
|
||
content: "";
|
||
}
|
||
}
|
||
|
||
.el-descriptions-item__container {
|
||
margin: 0 10px;
|
||
.no-colon {
|
||
margin: 0;
|
||
&::after {
|
||
content: "";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|