Files
dvcp_v2_webapp/project/fengdu/AppBIBoard/AppBIBoard.vue
2023-10-24 18:17:56 +08:00

938 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="AppBIBoard" :class="{fullscreen}">
<ai-fit-view @scale="v=>scale=v">
<ai-dv-wrapper ref="fddv" title="丰收号-家庭互助" :instance="instance" :mask="false">
<template v-slot:head="head">
<fengdu-head v-model="areaId" v-bind="head" @fullscreen="handleFullScreen" @setting="handleSetting"/>
</template>
<div class="left">
<fd-card label="社群动态概况">
<div class="grid c-2 pad-t14 pad-b20">
<div class="staPanel" v-for="(v,k) in sta" :key="k">
<div v-text="k"/>
<b v-text="v"/>
</div>
<div class="chart">
<div class="title">群活跃率7</div>
<ai-echart :ops="chart" :data="calcProgress(chartData)">
<div class="legend">
<ai-highlight v-for="item in chartData" :key="item.name" :content="`@v${item.value}`"
:value="item.name" color="#9BB7D4" class="flex center mar-b8"/>
</div>
</ai-echart>
</div>
<div class="chart">
<div class="title">人员活跃7</div>
<ai-echart :ops="chart" :data="calcProgress(chartData2)">
<div class="legend">
<ai-highlight v-for="item in chartData2" :key="item.name" :content="`@v${item.value}`"
:value="item.name" color="#9BB7D4" class="flex center mar-b8"/>
</div>
</ai-echart>
</div>
</div>
</fd-card>
<fd-card class="mar-t14" label="志愿者">
<div class="jumpBtn" slot="right" @click="handleJump">前往志愿者平台
<div class="el-icon-position"/>
</div>
<div class="staPanel simple flex mar-t10">
<div class="fill" v-for="(v,k) in volunteers" :key="k">
<div v-text="k"/>
<b v-text="v"/>
</div>
</div>
<div class="flex mar-v12">
<b class="fill title">志愿者名单</b>
<ai-select class="areaPicker" placeholder="团队选择"/>
</div>
<dv-scroll-board ref="volunteerTable" :config="volunteerConfig"/>
<div class="dots flex center">
<div class="dot" v-for="i in tablePages" :key="i" :class="{current:current==i}"/>
</div>
</fd-card>
</div>
<div class="center fill relative">
<fd-map ref="map" class="w100 h100" v-model="map" :root="areaId"/>
<fd-card class="centerBottom pad-b8" label="实时动态">
<dv-scroll-board class="mar-t14" :config="realtimeEvents" style="height: 114px"
@click="handleRealtimeEventDialog"/>
</fd-card>
</div>
<div class="right">
<fd-card label="功德银行">
<template #right>
<div class="shortcut" v-for="cut in shortcuts" :key="cut.k" @click="shortcut=cut.k"
:class="{active:shortcut==cut.k}" v-text="cut.v"/>
</template>
<div class="boxSta flex">
<div class="flex text">
<div>获取总积分</div>
<p v-text="GongdeBank.total"/>
</div>
</div>
<div class="staPanel simple right flex mar-t14">
<div class="fill" v-for="(v,k) in GongdeBank.users" :key="k">
<div v-text="k"/>
<b v-text="v"/>
</div>
</div>
<div class="boxSta flex">
<div class="flex text">
<div>兑换总积分</div>
<p v-text="GongdeBank.useTotal"/>
</div>
</div>
<div class="staPanel simple right flex mar-t14">
<div class="fill" v-for="(v,k) in GongdeBank.stores" :key="k">
<div v-text="k"/>
<b v-text="v"/>
</div>
</div>
<div class="grid c-3 pad-t14 pad-b20">
<div class="staPanel" v-for="(v,k) in GongdeBank.tasks">
<div v-text="k"/>
<b v-text="v"/>
</div>
</div>
</fd-card>
<fd-card label="门户应用统计" class="mar-t14 pad-b20">
<dv-scroll-board class="mar-t14" :config="appSta" style="height: 304px"/>
</fd-card>
</div>
</ai-dv-wrapper>
<fd-dialog v-model="dialog" :title="detail.eventType">
<template v-if="detail.mapType=='store'">
<b class="title mar-t8 mar-b16">店铺商品</b>
<carousel autoplay :perPage="3" autoplayHoverPause navigationEnabled :paginationEnabled="false"
class="mar-h32"
navigationNextLabel=" " navigationPrevLabel="">
<slide class="goods" v-for="good in detail.goods" :key="good.id">
<img :src="good.goods.picUrl"/>
<div class="mar-t8" v-text="good.goods.title"/>
</slide>
</carousel>
<b class="title mar-t14 mar-b12">订单列表</b>
<dv-scroll-board :config="goodsConfig" style="height: 152px"/>
</template>
<template v-else-if="detail.mapType=='area'">
<div class="staPanel area right mar-t12 mar-b24 grid c-4">
<fd-item v-for="(v,k) in detail.sta" :key="k" :label="k"><b v-text="v"/></fd-item>
</div>
<div class="flex mar-b14">
<div class="shortcut" v-for="cut in areaStaTypes" :key="cut.k" @click="areaStaType=cut.k"
:class="{active:areaStaType==cut.k}" v-text="cut.v"/>
</div>
<dv-scroll-board :config="areaTableConfig" style="height: 152px"/>
</template>
<template v-else>
<div v-if="detail.header" class="contentHead" v-html="detail.header"/>
<el-row type="flex" class="fill">
<el-carousel v-if="detail.imgs" class="fill">
<el-carousel-item v-for="(img,i) in detail.imgs" :key="i">
<el-image :src="img" :preview-src-list="detail.imgs"/>
</el-carousel-item>
</el-carousel>
<fd-scrollbar v-if="detail.form" class="fill mar-l24">
<fd-item v-for="(v,k) in detail.form" :key="k" :label="k" :value="v"/>
</fd-scrollbar>
<fd-scrollbar v-if="detail.content" class="fill mar-l14">
<div v-html="detail.content"/>
</fd-scrollbar>
</el-row>
</template>
</fd-dialog>
</ai-fit-view>
</section>
</template>
<script>
import AiFitView from "dui/packages/layout/AiFitView.vue";
import FengduHead from "./components/fengduHead.vue";
import FdCard from "./components/fdCard.vue";
import AiEchart from "dui/packages/tools/AiEchart.vue";
import AiHighlight from "dui/packages/layout/AiHighlight.vue";
import AiInfoItem from "dui/packages/basic/AiInfoItem.vue";
import AiWrapper from "dui/packages/basic/AiWrapper.vue";
import Vue from "vue";
import {scrollBoard} from "@jiaminghi/data-view"
import FdMap from "./components/fdMap.vue";
import FdDialog from "./components/fdDialog.vue";
import FdItem from "./components/fdItem.vue";
import FdScrollbar from "./components/fdScrollbar.vue";
import {Carousel, Slide} from "vue-carousel"
const tableConfigs = {
headerBGC: 'rgba(33, 180, 253, 0.1)',
oddRowBGC: 'rgba(112, 112, 112, 0)',
evenRowBGC: 'rgba(112, 112, 112, 0)',
headerHeight: 38,
rowNum: 3,
}
export default {
name: "AppBIBoard",
label: "丰都指挥舱",
components: {
FdScrollbar, Carousel, Slide,
FdItem, FdDialog, FdMap, AiWrapper, AiInfoItem, AiHighlight, AiEchart, FdCard, FengduHead, AiFitView
},
props: {
instance: Function,
dict: Object
},
data() {
return {
areaId: '',
scale: 1,
fullscreen: false,
sta: {},
chart: {
legend: {show: false},
series: {
type: 'gauge',
startAngle: 90,
endAngle: -270,
center: ['50%', 74],
radius: 50,
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{offset: 0, color: '#139AFF'},
{offset: 1, color: '#0ED5A6'},
]
}
},
},
pointer: {show: false},
splitLine: {show: false},
axisTick: {show: false},
axisLabel: {show: false},
axisLine: {
lineStyle: {width: 6, color: [[1, 'rgba(102, 121, 138, 0.4)']]},
},
detail: {
valueAnimation: true,
offsetCenter: [0, 0],
fontSize: 24,
formatter: '{value}%',
color: "#02FEFF",
fontFamily: "DIN",
width: 50,
lineHeight: 50,
padding: 12,
borderWidth: 1,
borderColor: 'rgba(102, 121, 138, 0.4)',
borderRadius: 50
},
},
},
chartData: [
// {name: "活跃居民群", value: 3502},
// {name: "全部居民群", value: 5118},
],
chartData2: [],
volunteers: {
团队数量: 125,
志愿者数量: 13,
服务学员数量: 5
},
volunteerConfig: {
...tableConfigs,
header: ['所属团队', '姓名', '性别', '年龄'],
rowNum: 4,
columnWidth: [250],
align: ['left', 'left', 'left', 'center'],
carousel: 'page',
data: [
['三合街道丁庄社区互助会', '张珊珊', '女', 32],
['三合街道丁庄社区互助会', '王富贵', '女', 32],
['三合街道丁庄社区互助会', '阿萨德', '男', 23],
['三合街道丁庄社区互助会', '阿连德', '男', 54],
['三合街道丁庄社区互助会', '王柏柏', '女', 66],
['三合街道丁庄社区互助会', '赵二狗', '男', 41],
['三合街道丁庄社区互助会', '唯一键', '女', 13],
['三合街道丁庄社区互助会', '卡萨丁', '男', 32],
['三合街道丁庄社区互助会', '卡萨丁', '男', 32],
['三合街道丁庄社区互助会', '卡萨丁', '男', 32],
['三合街道丁庄社区互助会', '张珊珊', '女', 32],
['三合街道丁庄社区互助会', '张珊珊', '女', 32],
]
},
appSta: {
...tableConfigs,
header: ['应用名称', '本日点击', '累计点击'],
rowNum: 7,
columnWidth: [250],
align: ['left', 'right', 'right'],
data: [
// ['渝快办', 178, 266],
// ['公交乘车码', 178, 266],
// ['警快办', 178, 266],
// ['医保电子凭证', 178, 266],
// ['居民上报', 178, 266],
// ['医保电子凭证', 178, 266],
// ['居民上报', 178, 266],
]
},
current: 1,
realtimeEvents: {
...tableConfigs,
columnWidth: [226],
align: ['center', 'left'],
data: [
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '汇南社区-张三 创建了新的居民群'],
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '汇南社区-张三 邀请居民"蓝天白云"加入居民群“书院社区2群”'],
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '汇南社区-张三 将居民"蓝天白云"踢出居民群 “书院社区2群”'],
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '滨江东路社区居民-陈思宇在丰收号小程序中进行了打卡签到'],
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '滨江东路社区居民-陈思宇在丰收号小程序中进行了积分申请'],
// ['<div class="timeRow">2023-10-19 14:55:32</div>', '滨滨江东路社区居民-陈思宇在丰收号小程序中进行了物品兑换'],
// ['<div class="timeRow">2023-10-18 14:55:32</div>', '三角路社区居民-陈思宇在丰收号小程序中进行了物品兑换'],
// ['<div class="timeRow">2023-10-18 14:55:32</div>', '三角路社区居民-陈思宇在丰收号小程序中进行了物品兑换'],
// ['<div class="timeRow">2023-10-18 14:55:32</div>', '三角路社区居民-陈思宇在丰收号小程序中进行了物品兑换'],
]
},
shortcut: 3,
GongdeBank: {},
map: null,
dialog: false,
detail: {},
areaStaType: 'grid'
}
},
computed: {
tablePages: v => Math.ceil(v.volunteerConfig.data.length / v.volunteerConfig.rowNum) || 0,
shortcuts: () => [
{k: '3', v: '昨日'},
{k: '0', v: '近七天'},
{k: '1', v: '近30天'},
{k: '2', v: '近一年'},
],
areaStaTypes: () => [
{k: 'grid', v: '网格'},
{k: 'resident', v: '居民群'},
{k: 'volunteer', v: '互助会'},
],
goodsConfig: v => ({
...tableConfigs,
header: ['兑换人', '兑换商品', '数量', '积分', '状态'],
data: v.detail.orders?.map(e => [e.integralUserName, e.goodsTitle, e.quantity, e.goodsIntegralPrice,
`<div class="statusTag ${e.status > 0 ? 'success' : ''}">${v.dict.getLabel('integralSGOStatus', e.status)}</div>`]),
align: ['left', 'left', 'right', 'right', 'center'],
}),
areaTableConfig: v => ({
...tableConfigs,
...{
grid: {
header: ['村/社区', '网格名称', '网格员人数'],
align: ['left', 'left', 'right'],
data: v.detail.girdList?.map(e => [e.parentGirdName, e.girdName, e.girdMemberCount])
},
resident: {
header: ['群名称', '群主', '群人数'],
align: ['left', 'left', 'right'],
columnWidth: [250],
data: v.detail.groupList?.map(e => [e.name, e.ownerName, e.memberCount])
},
volunteer: {
header: ['互助会名称', '会长', '会员数'],
align: ['left', 'left', 'right'],
columnWidth: [250],
data: v.detail.volunteers?.map(e => [e.name, e.ownerName, e.memberCount])
}
}[v.areaStaType]
})
},
watch: {
shortcut() {
this.getGdyh(this.areaId)
},
dialog(v) {
!v && (this.detail = {})
},
areaId(v) {
!!v && this.getData()
}
},
methods: {
handleFullScreen() {
this.fullscreen = this.$refs.fddv.handleFullScreen()
},
handleSetting(v) {
this.$refs.fddv.dialog = v
},
calcProgress(data = []) {
const value = data.length > 0 ? (data[0].value / data.at(-1).value * 100 || 0).toFixed(0) : 0
return [{value}]
},
watchTablePageChange(c = 0) {
if (this.$refs.volunteerTable) {
this.$refs.volunteerTable.$watch('animationIndex', i => {
this.current = Math.floor(i / 4) + 1
})
} else if (c < 5) {
setTimeout(() => this.watchTablePageChange(++c), 500)
}
},
getData(c = 0) {
const {areaId} = this.$data
if (areaId) {
this.getMiniAppInfo()
this.getRealTimeDynamic(areaId)
this.getWxGroupOverview(areaId)
this.getGdyh(areaId)
this.getMapData(areaId)
} else if (c < 10) setTimeout(() => this.getData(++c), 500)
else console.error(`尝试${c}次加载数据,无法过去数据`)
},
getMiniAppInfo() {
this.instance.post("/app/fdDiy/miniAppInfo").then(res => {
if (res?.data) {
const data = res.data.map(e => [e.name || "应用", e.lastDayClick, e.totalClick])
this.appSta = {...this.appSta, data}
}
})
},
getRealTimeDynamic(areaId) {
this.instance.post("/app/fdDiy/realTimeDynamic", null, {params: {areaId}}).then(res => {
if (res?.data) {
const meta = res.data,
data = meta.map(e => [`<div class="timeRow">${e.eventTime}</div>`, `<div class="flex">${e.bizId ? e.description.replace(e.type, `<div class="blue">${e.type}</div>`) : e.description}</div>`])
this.realtimeEvents = {...this.realtimeEvents, data, meta}
}
})
},
getWxGroupOverview(areaId) {
this.instance.post("/app/fdDiy/wxGroupOverview", null, {params: {areaId}}).then(res => {
if (res?.data) {
const {群数量 = 0, 群主人数 = 0, 群成员数量 = 0} = res.data
this.sta = {
群数量, 群主人数,
'群人员活跃数(30天)': Number(res.data['群人员活跃数(30天)']).toLocaleString(),
'群消息数(30天)': Number(res.data['群消息数(30天)']).toLocaleString(),
}
this.chartData = [
{name: "活跃居民群", value: Math.ceil(res.data["活跃居民群数量(7天)"] / 7)},
{name: "全部居民群", value: 群数量},
]
this.chartData2 = [
{name: "活跃居民数", value: res.data["活跃群成员数量(7天)"]},
{name: "群成员数量", value: 群成员数量},
]
}
})
},
getGdyh(areaId) {
this.instance.post("/app/fdDiy/gdyh", null, {params: {areaId, type: this.shortcut}}).then(res => {
if (res?.data) {
const {
宣发发布任务数 = 0,
宣发未审核数 = 0,
宣发审核通过数 = 0,
店铺总数 = 0,
店品库存量 = 0,
兑换物品数量 = 0,
获取积分总数: total = 0,
居民签到人次: 签到人数 = 0,
积分申请次数: 申请人数 = 0,
兑换总积分: useTotal = 0
} = res.data
this.GongdeBank = {
total, useTotal,
users: {
参与人数: 签到人数 + 申请人数,
申请人数,
签到人数
},
stores: {店铺总数, 店品库存量, 兑换物品数量},
tasks: {
宣发发布任务数,
审核通过率: (宣发审核通过数 / 宣发发布任务数 * 100 || 0).toFixed(2) + "%",
宣发未审核数,
}
}
}
})
},
getMapData(areaId) {
const initMap = new Promise(resolve => {
const load = (c = 0) => {
if (this.map) {
resolve()
} else if (c < 10) setTimeout(() => load(++c), 500)
}
load()
})
this.instance.post("/app/appintegralsupermarketshop/list", null, {params: {areaId, size: 9999}}).then(res => {
if (res?.data) {
initMap.then(() => {
this.map.clear()
this.$refs.map.init()
const {records} = res.data
this.map.on('click', e => {
console.log(e)
if (e.data?.marker == 'store') {//点击店铺
this.getMapStore(e.data)
} else if (e.data?.unique_id) {//点击地区
this.getMapArea(e.data)
}
})
this.map.setOption({
series: {
markPoint: {
symbolSize: 24,
label: {
show: true,
position: 'right',
formatter: '{b}',
distance: 2
},
data: records.map(e => ({
...e,
marker: 'store',
coord: [e.lng, e.lat],
name: e.title,
label: {color: "#FECA86"},
symbol: "image://https://cdn.cunwuyun.cn/fengdu/fdStoreIcon.png",
}))
}
}
})
})
}
})
},
getMapStore(store = {}) {
this.instance.post("/app/fdDiy/mapShopInfo", null, {params: {id: store.id}}).then(res => {
if (res?.data) {
this.dialog = true
this.detail = {eventType: store.name, mapType: store.marker, ...res.data}
}
})
},
getMapArea(area) {
this.instance.post("/app/fdDiy/mapAreaInfo", null, {params: {areaId: area.unique_id.padEnd(12, '0')}}).then(res => {
if (res?.data) {
this.dialog = true
const {村社区数量, 居民群数量, 居民数, 网格数, 群成员数量, 户数, 互助会 = 0, 会员数量 = 0} = res.data
this.detail = {
eventType: area.name,
mapType: 'area', ...res.data,
sta: {村社区数量, 居民群数量, 居民数, 网格数, 群成员数量, 户数, 互助会, 会员数量}
}
}
})
},
handleRealtimeEventDialog({rowIndex}) {
const row = this.realtimeEvents.meta[rowIndex]
if (row.bizId) {
const action = {
积分申请: "/app/appintegraluserapply/queryDetailById",
物品兑换: "/app/appintegralsupermarketorder/queryDetailById",
精选动态: "/app/appcontentinfo/queryDetailById",
}[row.type]
this.instance.post(action, null, {params: {id: row.bizId}}).then(res => {
if (res?.data) {
this.dialog = true
if (row.type == '积分申请') {
const {
applyItemName: 事件类型,
integralUserName: 申请人,
areaName: 所属地区,
createTime: 申请时间,
girdName: 所属网格,
content: 事件描述,
applyIntegral: 积分值,
phone: 手机号,
status,
files
} = res.data
this.detail.imgs = files?.map(e => e.accessUrl)
this.detail.form = {
事件类型,
申请人,
所属地区,
申请时间,
事件描述,
积分值,
手机号,
所属网格,
状态: `<div class="statusTag ${status > 0 ? 'success' : ''}">${this.dict.getLabel('appIntegralApplyEventStatus', status)}</div>`
}
} else if (row.type == '物品兑换') {
const {
status,
examineUserName: 核销人,
examineTime: 核销时间,
goodsPicUrl,
integralUserName: 兑换人,
goodsTitle: 兑换商品,
quantity: 数量,
usedIntegral: 消耗积分,
createTime: 兑换时间,
agentOrder
} = res.data
this.detail.imgs = [goodsPicUrl].flat().filter(Boolean) || []
this.detail.form = {
兑换人,
兑换商品,
数量,
消耗积分,
是否代兑换: this.dict.getLabel("yesOrNo", agentOrder),
兑换时间,
状态: `<div class="statusTag ${status > 0 ? 'success' : ''}">${this.dict.getLabel('appIntegralApplyEventStatus', status)}</div>`,
核销人,
核销时间
}
} else if (row.type == '精选动态') {
const {content, files, title, createUserName, girdName} = res.data
this.detail.imgs = files?.map(e => e.accessUrl)
this.detail.content = content
this.detail.header = ` <b>${title}</b>
<div class="flex normal mar-t8">
<div>${girdName}</div>
<div class="mar-l8">${createUserName}</div>
</div>`
}
this.detail = {eventType: row.type, ...this.detail}
}
})
}
},
handleJump() {
window.open("http://datas.fdxjtjyhzzyfw.cn/")
}
},
created() {
Vue.use(scrollBoard)
this.getData()
this.dict.load('appIntegralApplyEventStatus', 'yesOrNo', 'integralSGOStatus')
},
mounted() {
this.watchTablePageChange()
}
}
</script>
<style scoped lang="scss">
.AppBIBoard {
color: #CDDBEA;
font-size: 14px;
:deep(.areaPicker) {
max-width: 300px;
input {
background: rgba(0, 54, 82, 0.9);
border: 1px solid rgba(42, 122, 146, 0.7);
border-radius: 2.2px;
color: #B3DDE5;
cursor: pointer;
}
.el-input__suffix {
color: #B3DDE5;
}
}
&.fullscreen {
position: fixed;
z-index: 202310111819;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
:deep(.viewPanel) {
background-image: url("./assets/img_bg.png");
& > .fill {
display: flex;
gap: 20px;
padding: 12px 24px 0;
}
}
.left, .right {
width: 480px;
flex-shrink: 0;
}
.grid {
display: grid;
gap: 14px;
&.c-2 {
grid-template-columns:1fr 1fr;
}
&.c-3 {
grid-template-columns:1fr 1fr 1fr;
}
&.c-4 {
grid-template-columns:1fr 1fr 1fr 1fr;
}
}
.staPanel {
text-align: center;
font-size: 15px;
line-height: 20px;
background: url("./assets/staPanel-bg.png") no-repeat;
background-size: 100% 100%;
height: 80px;
padding-top: 14px;
width: 100%;
b {
font-family: DIN;
font-size: 22px;
color: #02FEFF;
letter-spacing: 0;
line-height: 36px;
}
&.simple {
background: #ffffff0a;
padding-top: 0;
&.right {
color: #9BB7D4;
b {
color: #FFFFFF;
}
}
}
&.area {
background: #ffffff0a;
padding: 16px 8px;
gap: 14px;
b {
font-size: 16px;
color: #FFFFFF;
line-height: 16px;
}
:deep(.fdItem) {
margin-bottom: 0;
& > label {
color: #9BB7D4;
}
}
}
}
.chart {
.legend {
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.AiEchart {
height: 204px;
}
}
.title {
padding-left: 10px;
line-height: 30px;
background-image: linear-gradient(270deg, #1f436600 0%, #245a7570 99%);
}
.jumpBtn {
background-image: linear-gradient(180deg, rgba(90, 200, 246, 0.4) 0%, rgba(1, 51, 101, 0.4) 84%);
box-shadow: inset 0 2px 8px 0 rgba(51, 187, 255, 0.5);
border-radius: 15px;
font-weight: 500;
font-size: 12px;
color: #02FEFF;
padding: 8px 16px;
height: 30px;
user-select: none;
cursor: pointer;
margin-top: -7px;
}
:deep(.dv-scroll-board) {
height: 200px;
.header-item {
color: #02FEFF;
}
.row-item {
height: 38px;
line-height: 38px;
border-bottom: 1px solid #154270;
margin-top: -1px;
}
.timeRow {
background-image: url("./assets/realtimeIcon.png");
background-repeat: no-repeat;
background-position: 20px center;
text-indent: 24px;
}
.blue {
color: #02FEFF;
cursor: pointer;
}
.ceil > .statusTag {
margin-top: 19px;
transform: translateY(-50%);
}
}
.dots {
height: 36px;
padding-top: 22px;
padding-bottom: 8px;
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #679a9a80;
margin-right: 8px;
&.current {
background: #02FEFF;
}
&:last-of-type {
margin-right: 0;
}
}
}
.centerBottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
.shortcut {
background: #1f9ecc29;
padding: 4px 13px;
color: #1FBECC;
font-size: 13px;
margin-left: 4px;
margin-top: -7px;
border: 1px solid transparent;
cursor: pointer;
height: fit-content;
&:first-of-type {
margin-left: 0;
}
&.active {
border-color: #20B4C5;
color: #4ED8E4;
}
}
.boxSta {
margin-top: 16px;
padding-right: 40px;
justify-content: flex-end;
background: url("./assets/box.png") no-repeat 80px center;
height: 82px;
font-size: 16px;
.text {
color: #FFFFFF;
width: 200px;
justify-content: space-between;
& > p {
font-family: DIN;
font-size: 26px;
color: #02FEFF;
}
}
}
:deep(.statusTag ) {
height: 20px;
line-height: 20px;
padding: 0 8px;
color: #FFB300;
background: #ffcb5224;
width: fit-content;
&.success {
color: #07B794;
background: #13f6c924;
}
}
:deep(.contentHead) {
width: 100%;
height: 89px;
background: url("./assets/contentHead.png") no-repeat;
margin-top: 16px;
margin-bottom: 14px;
padding: 16px;
background-size: 100% 89px;
& > b {
font-size: 16px;
color: #02FEFF;
letter-spacing: 0;
}
}
:deep(.VueCarousel) {
.goods {
font-size: 16px;
color: #02FEFF;
text-align: center;
& > img {
background: url("./assets/goodBg.png");
padding: 10px;
width: 130px;
height: 138px;
}
}
.VueCarousel-navigation-button {
width: 32px;
height: 32px;
background: url("./assets/carousel-nav-btn.png") no-repeat;
outline: none;
border-color: transparent;
&.VueCarousel-navigation-next {
transform: translate(100%, -50%) rotate(180deg);
}
&:active {
opacity: .8;
}
}
}
}
</style>