2024-06-27 18:01:47 +08:00
|
|
|
<script>
|
|
|
|
|
export default {
|
|
|
|
|
name: "AppCarouselList",
|
|
|
|
|
label: "分柜监控",
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
height: '600px',
|
2024-06-27 22:39:41 +08:00
|
|
|
list: [],
|
2024-06-27 18:01:47 +08:00
|
|
|
cameras: [],
|
|
|
|
|
storeKeyGoods: [],
|
|
|
|
|
categorySales: [],
|
|
|
|
|
columns: {
|
|
|
|
|
品类销售情况: [
|
|
|
|
|
{label: "品类", prop: "secondCategoryName"},
|
2024-07-07 22:42:40 +08:00
|
|
|
{label: "销售额", prop: "currentSaleAmt", width: 70},
|
|
|
|
|
{label: "库存金额", prop: "currentStockAmt", width: 80},
|
|
|
|
|
{label: "同/环比销售额", prop: "compareSaleAmt", width: 70},
|
|
|
|
|
{label: "同/环比库存金额", prop: "compareStockAmt", width: 70},
|
2024-08-01 23:48:46 +08:00
|
|
|
{label: "前四周日均销售额", prop: "avg4WeekSaleAmt", width: 70},
|
2024-06-27 18:01:47 +08:00
|
|
|
],
|
|
|
|
|
重点单品情况: [
|
2024-07-08 18:53:50 +08:00
|
|
|
{label: "重点单品", prop: "goodsName"},
|
2024-07-07 22:42:40 +08:00
|
|
|
{label: "当日目标", prop: "targetNum", width: 70},
|
|
|
|
|
{label: "销售数量", prop: "saleNum", width: 70},
|
|
|
|
|
{label: "库存数量", prop: "stockNum", width: 70},
|
2024-06-27 18:01:47 +08:00
|
|
|
{label: "剩余时间预计销售数量", prop: "preSaleNum"},
|
|
|
|
|
{label: "提醒", custom: 1, width: 70, align: 'center', prop: "remind"},
|
2024-07-08 18:53:50 +08:00
|
|
|
],
|
|
|
|
|
周边库存情况: [
|
|
|
|
|
{label: "门店名称", prop: "storeName"},
|
|
|
|
|
{label: "直线距离", prop: "distance", width: 70},
|
|
|
|
|
{label: "库存数量", prop: "stockNum", width: 70},
|
|
|
|
|
{label: "销售数量", prop: "saleNum", width: 70},
|
|
|
|
|
{label: "剩余时间预计销售数量", prop: "preSaleNum", width: 70},
|
|
|
|
|
{label: "店长姓名/电话", prop: "shopMangerName", format: v => v.shopMangerName ? `${v.shopMangerName}(${v.shopownerPhone})` : ""},
|
2024-06-27 18:01:47 +08:00
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-07-07 22:42:40 +08:00
|
|
|
computed: {
|
|
|
|
|
search: v => v.$storeBoard.search,
|
|
|
|
|
},
|
2024-06-27 18:01:47 +08:00
|
|
|
methods: {
|
|
|
|
|
getData() {
|
2024-06-27 22:39:41 +08:00
|
|
|
const {$waitFor, $http} = window
|
2024-06-27 18:01:47 +08:00
|
|
|
console.log("筛选条件:", this.search)
|
2024-06-27 22:39:41 +08:00
|
|
|
$waitFor($http).then(() => Promise.all([this.getCameras(), this.getStoreKeyGoods(), this.getCategorySales()]))
|
2024-06-27 18:01:47 +08:00
|
|
|
.then(() => {
|
2024-06-27 22:39:41 +08:00
|
|
|
this.list = [
|
|
|
|
|
{label: "西点柜", value: "104"},
|
|
|
|
|
{label: "现烤柜", value: "108"},
|
|
|
|
|
{label: "蛋糕柜", value: "109"},
|
|
|
|
|
].map(({label, value: categoryId}) => {
|
2024-07-08 18:53:50 +08:00
|
|
|
const {storeCameraVOList = [], longitude, latitude, storeCode, storeName} = this.cameras.find(e => e.storeCode == this.search.storeCode) || {}
|
|
|
|
|
this.$storeBoard.store = {longitude, latitude, storeCode, storeName}
|
|
|
|
|
const keyGoods = this.storeKeyGoods.filter(e => e.goodsCategoryId == categoryId) || []
|
2024-06-27 22:39:41 +08:00
|
|
|
const categorySale = this.categorySales.filter(e => e.secondCategoryId == categoryId) || []
|
2024-07-08 18:53:50 +08:00
|
|
|
return {longitude, latitude, categoryId, label, camera: storeCameraVOList.filter(e => e.cameraType == categoryId).map(e => e.cameraUrl), keyGoods, categorySale}
|
2024-06-27 18:01:47 +08:00
|
|
|
}) || []
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
getCameras() {
|
|
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/storeCamera", {
|
2024-07-07 22:47:46 +08:00
|
|
|
type: "1", ...this.search,
|
2024-06-27 18:01:47 +08:00
|
|
|
}).then(res => {
|
|
|
|
|
if (res?.data) {
|
2024-07-08 18:53:50 +08:00
|
|
|
this.cameras = res.data?.records || []
|
2024-06-27 18:01:47 +08:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
getStoreKeyGoods() {
|
2024-06-27 22:39:41 +08:00
|
|
|
return $http.post("/data-boot/la/screen/singleStoreBoard/singStoreKeyGoodsSale", {
|
2024-08-05 03:28:19 +08:00
|
|
|
type: "1", ...this.search,
|
2024-06-27 18:01:47 +08:00
|
|
|
}).then(res => {
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
this.storeKeyGoods = res.data
|
2024-08-08 14:30:02 +08:00
|
|
|
this.$set(this.$storeBoard, 'storeKeyGoods', res.data.filter(e => !/(104|108|109)/.test(e.goodsCategoryId)))
|
2024-06-27 18:01:47 +08:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
getCategorySales() {
|
2024-06-27 22:39:41 +08:00
|
|
|
return $http.post("/data-boot/la/screen/singleStoreBoard/singStoreCategorySale", {
|
2024-07-07 22:47:46 +08:00
|
|
|
type: "1", ...this.search,
|
2024-06-27 18:01:47 +08:00
|
|
|
}).then(res => {
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
this.categorySales = res.data
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
2024-07-08 18:53:50 +08:00
|
|
|
getTableData(item = {}, tag) {
|
2024-07-07 22:42:40 +08:00
|
|
|
const v = this
|
|
|
|
|
const datasource = {
|
2024-07-08 18:53:50 +08:00
|
|
|
重点单品情况: item.keyGoods,
|
|
|
|
|
品类销售情况: item.categorySale,
|
|
|
|
|
周边库存情况: v.$storeBoard.aroundStock,
|
2024-07-07 22:42:40 +08:00
|
|
|
}
|
|
|
|
|
return {
|
2024-07-08 18:53:50 +08:00
|
|
|
headerBGC: 'rgba(13, 48, 99, 0.6)', rowNum: arguments?.[2] || 2,
|
2024-07-07 22:42:40 +08:00
|
|
|
oddRowBGC: window.evenRowBGC(), evenRowBGC: "transparent",
|
|
|
|
|
header: v.columns[tag].map(e => e.label),
|
|
|
|
|
columnWidth: v.columns[tag].map(e => e.width || "0;flex:1;min-width:0;"),
|
|
|
|
|
align: v.columns[tag].map(e => e.align || "left"),
|
2024-07-08 18:53:50 +08:00
|
|
|
data: datasource[tag]?.map(e => v.columns[tag].map(column => column.custom == 1 ? `<div class="pointer" style="color:${e.preSaleNum > e.stockNum ? 'red' : '#fff'}">周边库存</div>` :
|
|
|
|
|
column.format ? column.format(e) : e[column.prop])) || [],
|
2024-07-07 22:42:40 +08:00
|
|
|
}
|
|
|
|
|
},
|
2024-08-05 03:28:19 +08:00
|
|
|
openNearbyStores({thirdGoodsCode}, store) {
|
|
|
|
|
const {longitude, latitude} = store
|
2024-07-08 18:53:50 +08:00
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/aroundStock", {
|
2024-08-05 03:28:19 +08:00
|
|
|
type: "1", ...this.search, longitude, latitude, thirdGoodsCode,
|
2024-07-08 18:53:50 +08:00
|
|
|
}).then(res => {
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
this.$storeBoard.aroundStock = res.data
|
|
|
|
|
this.$nextTick(() => this.$storeBoard.dialog = true)
|
|
|
|
|
}
|
|
|
|
|
})
|
2024-08-08 14:38:16 +08:00
|
|
|
},
|
|
|
|
|
getCameraUrl(item) {
|
|
|
|
|
return item.camera?.[0]
|
2024-07-07 22:42:40 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
search: {
|
|
|
|
|
immediate: true, deep: true, handler() {
|
|
|
|
|
this.getData()
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-27 18:01:47 +08:00
|
|
|
},
|
|
|
|
|
mounted() {
|
2024-07-08 18:53:50 +08:00
|
|
|
window.addEventListener("click", () => {
|
|
|
|
|
this.$storeBoard.dialog = false
|
|
|
|
|
})
|
2024-06-27 18:01:47 +08:00
|
|
|
this.height = `${this.$el.clientHeight}px`
|
2024-07-08 18:53:50 +08:00
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
window.removeEventListener("click", () => {
|
|
|
|
|
this.$storeBoard.dialog = false
|
|
|
|
|
})
|
2024-06-27 18:01:47 +08:00
|
|
|
}
|
2024-07-08 18:53:50 +08:00
|
|
|
|
2024-06-27 18:01:47 +08:00
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<section class="AppCarouselList">
|
|
|
|
|
<div class="layout">
|
2024-07-29 20:17:32 +08:00
|
|
|
<div class="store" v-for="store in list" :key="store.categoryId">
|
2024-07-07 22:42:40 +08:00
|
|
|
<div class="headerTitle" v-text="store.label"/>
|
2024-08-08 14:38:16 +08:00
|
|
|
<div class="camera">
|
|
|
|
|
<hls-player :id="`hls_player_${store.categoryId}`" :url="getCameraUrl(store)"/>
|
|
|
|
|
</div>
|
2024-06-27 18:01:47 +08:00
|
|
|
<div class="subTitle" v-text="'品类销售情况'"/>
|
2024-08-05 03:28:19 +08:00
|
|
|
<scroll-table :table-data="store.categorySale" :columns="columns['品类销售情况']"/>
|
|
|
|
|
<!--<dv-scroll-board :config="getTableData(store, '品类销售情况')"/>-->
|
2024-06-27 18:01:47 +08:00
|
|
|
<div class="subTitle" v-text="'重点单品情况'"/>
|
2024-08-05 03:28:19 +08:00
|
|
|
<scroll-table :table-data="store.keyGoods" :columns="columns['重点单品情况']" @click="v=>openNearbyStores(v,store)" @click.native.stop/>
|
|
|
|
|
<!--<dv-scroll-board :config="getTableData(store, '重点单品情况')" @click="v=>openNearbyStores(v,store)" @click.native.stop/>-->
|
2024-06-27 18:01:47 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-08-08 14:30:02 +08:00
|
|
|
<div class="dialogTable" v-if="$storeBoard.dialog" @click.stop>
|
2024-08-05 03:28:19 +08:00
|
|
|
<scroll-table :table-data="$storeBoard.aroundStock" :columns="columns['周边库存情况']"/>
|
|
|
|
|
</div>
|
2024-06-27 18:01:47 +08:00
|
|
|
</section>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.AppCarouselList {
|
|
|
|
|
color: #fff;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-05 03:28:19 +08:00
|
|
|
.AppCarouselList .dv-scroll-board, .AppCarouselList .scrollTable {
|
|
|
|
|
height: 200px !important;
|
2024-06-27 18:01:47 +08:00
|
|
|
}
|
|
|
|
|
|
2024-07-07 22:42:40 +08:00
|
|
|
.AppCarouselList .headerTitle {
|
2024-06-27 18:01:47 +08:00
|
|
|
height: 48px;
|
|
|
|
|
padding: 8px 0 8px 38px;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
background-image: url("http://10.0.97.209/img/kengee/kengee4.png");
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
background-size: 100% 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.AppCarouselList .subTitle {
|
|
|
|
|
line-height: 20px;
|
|
|
|
|
width: fit-content;
|
|
|
|
|
margin: 24px auto 12px;
|
|
|
|
|
background-image: url("http://10.0.97.209/img/kengee/kengee5.png");
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
background-size: 100% 2px;
|
|
|
|
|
background-position: center bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.AppCarouselList .layout {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 24px;
|
|
|
|
|
width: 100%;
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.AppCarouselList .store {
|
|
|
|
|
width: calc(33% - 16px);
|
|
|
|
|
}
|
2024-08-08 14:38:16 +08:00
|
|
|
|
|
|
|
|
.AppCarouselList .camera {
|
|
|
|
|
height: 250px;
|
|
|
|
|
}
|
2024-06-27 18:01:47 +08:00
|
|
|
</style>
|