2024-06-17 18:20:13 +08:00
|
|
|
|
<script>
|
2024-07-08 12:15:10 +08:00
|
|
|
|
const currentDate = "20240705"
|
2024-06-17 18:20:13 +08:00
|
|
|
|
export default {
|
2024-06-18 17:09:25 +08:00
|
|
|
|
name: "AppStoresTable",
|
2024-06-17 23:18:11 +08:00
|
|
|
|
label: "多店监控",
|
2024-06-18 22:23:45 +08:00
|
|
|
|
components: {
|
|
|
|
|
|
HlsPlayer: {
|
|
|
|
|
|
render: (h) => h('div', {style: {width: '100%', height: '100%'}}),
|
|
|
|
|
|
props: {
|
|
|
|
|
|
url: {default: "https://open.ys7.com/v3/openlive/155715496_1_1.m3u8?expire=1747359002&id=712960386311127040&t=c9c6ad362940b1fb4ea7a736cec78980aa9ad1d27d6e3eddf75788c0564e9d7b&ev=100"}
|
|
|
|
|
|
},
|
|
|
|
|
|
mounted() {
|
|
|
|
|
|
const {Clappr} = window
|
|
|
|
|
|
if (Clappr && this.url) {
|
|
|
|
|
|
const player = new Clappr.Player({
|
|
|
|
|
|
source: this.url,
|
|
|
|
|
|
mute: true, //静音为true
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
// poster:'http://clappr.io/poster.png', //设置封面图
|
|
|
|
|
|
autoPlay: true,
|
|
|
|
|
|
disableCanAutoPlay: true, //禁用检测浏览器是否可以自动播放视频
|
|
|
|
|
|
hideMediaControl: true, //禁用媒体控制自动隐藏
|
|
|
|
|
|
hideMediaControlDelay: 100, //更改默认的媒体控件自动隐藏超时值
|
|
|
|
|
|
hideVolumeBar: true, //当嵌入的宽度小于320时,音量条将被隐藏
|
|
|
|
|
|
exitFullscreenOnEnd: false, //禁用播放器将在媒体结束时自动退出全屏显示,即播放结束后不会退出全屏
|
|
|
|
|
|
mediacontrol: {seekbar: "#000", buttons: "#FFF"}, //定义进度条和底部暂停等图标的颜色
|
|
|
|
|
|
events: {
|
|
|
|
|
|
onError: function () { //当播放出错时
|
|
|
|
|
|
alert("播放出错!")
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
player.attachTo(this.$el);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2024-06-17 23:18:11 +08:00
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2024-06-18 18:03:52 +08:00
|
|
|
|
height: '600px',
|
2024-06-18 22:23:45 +08:00
|
|
|
|
stores: [],
|
2024-06-20 18:31:15 +08:00
|
|
|
|
cameras: [],
|
|
|
|
|
|
storeKeyGoods: [],
|
|
|
|
|
|
categorySales: [],
|
2024-07-08 12:15:10 +08:00
|
|
|
|
aroundStock: [],
|
|
|
|
|
|
dialog: false,
|
2024-06-17 23:18:11 +08:00
|
|
|
|
columns: {
|
|
|
|
|
|
品类销售情况: [
|
2024-06-18 22:23:45 +08:00
|
|
|
|
{label: "品类", prop: "secondCategoryName"},
|
2024-07-07 11:27:52 +08:00
|
|
|
|
{label: "销售额", prop: "currentSaleAmt", width: 70},
|
|
|
|
|
|
{label: "库存金额", prop: "currentStockAmt", width: 80},
|
|
|
|
|
|
{label: "同/环比销售额", prop: "compareSaleAmt", width: 70},
|
|
|
|
|
|
{label: "同/环比库存金额", prop: "compareStockAmt", width: 70},
|
|
|
|
|
|
{label: "前四周日军销售额", prop: "avg4WeekSaleAmt", width: 70},
|
2024-06-17 23:18:11 +08:00
|
|
|
|
],
|
|
|
|
|
|
重点单品情况: [
|
2024-06-18 22:23:45 +08:00
|
|
|
|
{label: "重点单品", prop: "name"},
|
2024-07-07 11:27:52 +08:00
|
|
|
|
{label: "当日目标", prop: "targetNum", width: 70},
|
|
|
|
|
|
{label: "销售数量", prop: "saleNum", width: 70},
|
|
|
|
|
|
{label: "库存数量", prop: "stockNum", width: 70},
|
2024-06-18 22:23:45 +08:00
|
|
|
|
{label: "剩余时间预计销售数量", prop: "preSaleNum"},
|
|
|
|
|
|
{label: "提醒", custom: 1, width: 70, align: 'center', prop: "remind"},
|
2024-07-08 12:15:10 +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.shopownerPhone})`},
|
2024-06-17 23:18:11 +08:00
|
|
|
|
]
|
|
|
|
|
|
},
|
2024-07-08 12:15:10 +08:00
|
|
|
|
|
2024-06-17 23:18:11 +08:00
|
|
|
|
}
|
2024-06-18 18:03:52 +08:00
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
2024-06-20 18:31:15 +08:00
|
|
|
|
refs: v => v.$parent.getItemRefs(),
|
2024-07-07 11:27:52 +08:00
|
|
|
|
search: v => v.$multipleStoreBoard.search,
|
2024-06-18 18:03:52 +08:00
|
|
|
|
storeList: v => {
|
|
|
|
|
|
const list = []
|
|
|
|
|
|
let group = []
|
2024-06-18 22:23:45 +08:00
|
|
|
|
for (const e of v.stores) {
|
2024-06-18 18:03:52 +08:00
|
|
|
|
if (group.length < 4) {
|
|
|
|
|
|
group.push(e)
|
|
|
|
|
|
} else {
|
2024-06-18 22:23:45 +08:00
|
|
|
|
list.push(group.reverse())
|
2024-06-18 18:03:52 +08:00
|
|
|
|
group = [e]
|
|
|
|
|
|
}
|
2024-06-18 22:23:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (group.length > 0) list.push(group.reverse())
|
2024-06-18 18:03:52 +08:00
|
|
|
|
return list
|
2024-07-07 11:27:52 +08:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
search: {
|
|
|
|
|
|
immediate: true, deep: true, handler() {
|
|
|
|
|
|
this.getData()
|
|
|
|
|
|
}
|
2024-06-18 18:03:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2024-06-18 22:23:45 +08:00
|
|
|
|
methods: {
|
|
|
|
|
|
getData() {
|
2024-06-21 16:42:57 +08:00
|
|
|
|
const {$http, $waitFor} = window
|
2024-06-24 11:10:40 +08:00
|
|
|
|
console.log("筛选条件:", this.search)
|
2024-07-07 11:27:52 +08:00
|
|
|
|
$waitFor($http && this.search.groupCodeList.length > 0).then(() => this.getStores())
|
|
|
|
|
|
.then(codes => Promise.all([this.getCameras(), this.getStoreKeyGoods(), this.getCategorySales()]).then(() => codes))
|
|
|
|
|
|
.then((codes = []) => {
|
|
|
|
|
|
this.stores = codes?.map(storeCode => {
|
2024-07-08 12:15:10 +08:00
|
|
|
|
const {storeCameraVOList = [], storeName, longitude, latitude} = this.cameras.find(e => e.storeCode == storeCode) || {}
|
2024-06-21 18:02:03 +08:00
|
|
|
|
const keyGoods = this.storeKeyGoods.filter(e => e.storeCode == storeCode) || []
|
|
|
|
|
|
const categorySale = this.categorySales.filter(e => e.storeCode == storeCode) || []
|
2024-07-08 12:15:10 +08:00
|
|
|
|
return {storeCode, storeName, longitude, latitude, camera: storeCameraVOList.map(e => e.cameraUrl), keyGoods, categorySale}
|
2024-07-07 11:27:52 +08:00
|
|
|
|
}).filter(e => !!e.storeName) || []
|
2024-06-21 18:02:03 +08:00
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
getStores() {
|
2024-07-07 11:27:52 +08:00
|
|
|
|
const {groupCodeList = []} = this.search
|
|
|
|
|
|
return $http.get(`/data-boot/ca/screen/scStoreInfo/group/${groupCodeList[0]}`).then(res => {
|
2024-06-21 18:02:03 +08:00
|
|
|
|
if (res?.data) {
|
2024-07-07 11:27:52 +08:00
|
|
|
|
return res.data
|
2024-06-21 18:02:03 +08:00
|
|
|
|
}
|
2024-06-18 22:23:45 +08:00
|
|
|
|
})
|
2024-06-20 18:31:15 +08:00
|
|
|
|
},
|
|
|
|
|
|
getCameras() {
|
2024-06-21 15:59:59 +08:00
|
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/storeCamera", {
|
2024-07-07 22:47:46 +08:00
|
|
|
|
type: "1", ...this.search, limit: 999
|
2024-06-20 18:31:15 +08:00
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res?.data) {
|
2024-06-21 18:02:03 +08:00
|
|
|
|
this.cameras = res.data?.records || []
|
2024-06-20 18:31:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
getStoreKeyGoods() {
|
2024-06-21 15:59:59 +08:00
|
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/storeKeyGoods", {
|
2024-07-08 12:15:10 +08:00
|
|
|
|
type: "1", ...this.search, currentDate
|
2024-06-20 18:31:15 +08:00
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
|
this.storeKeyGoods = res.data
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
getCategorySales() {
|
2024-06-21 15:59:59 +08:00
|
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/categorySale", {
|
2024-07-07 22:47:46 +08:00
|
|
|
|
type: "1", ...this.search,
|
2024-06-20 18:31:15 +08:00
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
|
this.categorySales = res.data
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
2024-06-21 15:59:59 +08:00
|
|
|
|
gotoDetail(store) {
|
|
|
|
|
|
$glob.query = {storeCode: store.storeCode}
|
2024-06-21 16:42:57 +08:00
|
|
|
|
const sid = "9f299712-5549-413b-a93b-7c3e3b5bfadb"
|
|
|
|
|
|
$glob.group = sid
|
2024-07-07 11:27:52 +08:00
|
|
|
|
this.$storeBoard.query.storeCode = sid
|
2024-07-07 22:42:40 +08:00
|
|
|
|
this.$router.push("/apps/AppStoreBoard")
|
2024-06-21 15:59:59 +08:00
|
|
|
|
},
|
2024-07-08 12:15:10 +08:00
|
|
|
|
getTableData(item = {}, tag) {
|
2024-07-07 11:27:52 +08:00
|
|
|
|
const v = this
|
|
|
|
|
|
const datasource = {
|
2024-07-08 12:15:10 +08:00
|
|
|
|
重点单品情况: item.keyGoods,
|
|
|
|
|
|
品类销售情况: item.categorySale,
|
|
|
|
|
|
周边库存情况: v.aroundStock,
|
2024-07-07 11:27:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
return {
|
2024-07-08 12:15:10 +08:00
|
|
|
|
headerBGC: 'rgba(13, 48, 99, 0.6)', rowNum: arguments?.[2] || 2,
|
2024-07-07 11:27:52 +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 12:15:10 +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 11:27:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2024-07-08 12:15:10 +08:00
|
|
|
|
openNearbyStores({rowIndex}, store) {
|
|
|
|
|
|
const {thirdGoodsCode} = this.storeKeyGoods[rowIndex],
|
|
|
|
|
|
{storeCode, longitude, latitude} = store
|
|
|
|
|
|
return $http.post("/data-boot/la/screen/multipleStoreBoard/aroundStock", {
|
|
|
|
|
|
type: "1", ...this.search, storeCode, longitude, latitude, thirdGoodsCode, currentDate
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
|
this.aroundStock = res.data
|
|
|
|
|
|
this.$nextTick(() => this.dialog = true)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2024-07-07 11:27:52 +08:00
|
|
|
|
}
|
2024-06-18 22:23:45 +08:00
|
|
|
|
},
|
2024-06-21 15:59:59 +08:00
|
|
|
|
mounted() {
|
2024-06-18 18:03:52 +08:00
|
|
|
|
this.height = `${this.$el.clientHeight}px`
|
2024-06-17 23:18:11 +08:00
|
|
|
|
}
|
2024-06-17 18:20:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
2024-07-08 12:15:10 +08:00
|
|
|
|
<section class="AppStoresTable" @click="dialog=false">
|
2024-07-08 10:11:10 +08:00
|
|
|
|
<el-carousel indicator-position="none" :height="height" :autoplay="search.changeWay==1">
|
2024-06-18 18:03:52 +08:00
|
|
|
|
<el-carousel-item v-for="(group,i) in storeList" :key="i">
|
|
|
|
|
|
<div class="layout">
|
2024-06-21 15:59:59 +08:00
|
|
|
|
<div class="store" v-for="store in group" :key="store.storeCode">
|
2024-07-07 11:27:52 +08:00
|
|
|
|
<div class="headerTitle" v-text="store.storeName" @click="gotoDetail(store)"/>
|
2024-06-18 18:03:52 +08:00
|
|
|
|
<el-carousel indicator-position="none" height="250px">
|
2024-06-18 22:23:45 +08:00
|
|
|
|
<el-carousel-item v-for="(url,j) in store.camera" :key="[i,j].join('_')">
|
|
|
|
|
|
<hls-player :url="url"/>
|
|
|
|
|
|
</el-carousel-item>
|
2024-06-18 18:03:52 +08:00
|
|
|
|
</el-carousel>
|
2024-06-21 11:51:14 +08:00
|
|
|
|
<div class="subTitle" v-text="'品类销售情况'"/>
|
2024-07-07 11:27:52 +08:00
|
|
|
|
<dv-scroll-board :config="getTableData(store, '品类销售情况')"/>
|
2024-06-21 11:51:14 +08:00
|
|
|
|
<div class="subTitle" v-text="'重点单品情况'"/>
|
2024-07-08 12:15:10 +08:00
|
|
|
|
<dv-scroll-board :config="getTableData(store, '重点单品情况')" @click="v=>openNearbyStores(v,store)" @click.native.stop/>
|
2024-06-18 18:03:52 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-carousel-item>
|
|
|
|
|
|
</el-carousel>
|
2024-07-08 12:15:10 +08:00
|
|
|
|
<dv-scroll-board v-if="dialog" class="dialogTable" :config="getTableData({}, '周边库存情况',5)" @click.native.stop/>
|
2024-06-17 21:55:16 +08:00
|
|
|
|
</section>
|
2024-06-17 18:20:13 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
2024-07-07 11:27:52 +08:00
|
|
|
|
<style>
|
2024-06-18 17:09:25 +08:00
|
|
|
|
.AppStoresTable {
|
2024-07-07 11:27:52 +08:00
|
|
|
|
width: 100%;
|
2024-06-17 23:18:11 +08:00
|
|
|
|
color: #fff;
|
|
|
|
|
|
box-sizing: border-box;
|
2024-07-08 12:15:10 +08:00
|
|
|
|
position: relative;
|
2024-06-17 23:18:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-07 11:27:52 +08:00
|
|
|
|
.AppStoresTable .dv-scroll-board {
|
2024-07-08 12:15:10 +08:00
|
|
|
|
height: 130px;
|
2024-06-17 23:18:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-07 11:27:52 +08:00
|
|
|
|
.AppStoresTable .headerTitle {
|
2024-06-17 23:18:11 +08:00
|
|
|
|
height: 48px;
|
|
|
|
|
|
padding: 8px 0 8px 38px;
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
line-height: 32px;
|
2024-06-18 17:09:25 +08:00
|
|
|
|
background-image: url("http://10.0.97.209/img/kengee/kengee4.png");
|
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
background-size: 100% 100%;
|
2024-06-17 23:18:11 +08:00
|
|
|
|
}
|
2024-06-17 21:55:16 +08:00
|
|
|
|
|
2024-06-21 11:51:14 +08:00
|
|
|
|
.AppStoresTable .subTitle {
|
2024-06-17 23:18:11 +08:00
|
|
|
|
line-height: 20px;
|
2024-06-18 17:09:25 +08:00
|
|
|
|
width: fit-content;
|
2024-06-17 23:18:11 +08:00
|
|
|
|
margin: 24px auto 12px;
|
2024-06-18 17:09:25 +08:00
|
|
|
|
background-image: url("http://10.0.97.209/img/kengee/kengee5.png");
|
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
background-size: 100% 2px;
|
|
|
|
|
|
background-position: center bottom;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-18 22:23:45 +08:00
|
|
|
|
.AppStoresTable .layout {
|
2024-06-18 17:09:25 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 24px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-18 22:23:45 +08:00
|
|
|
|
.AppStoresTable .store {
|
2024-06-18 17:09:25 +08:00
|
|
|
|
width: calc(25% - 18px);
|
2024-06-17 18:20:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|