| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- <template>
- <div class="app-container home">
- <el-row :gutter="10" class="top_row">
- <el-col :span="8" class="box-card_bg" v-for="(item, index) in state.deviceListData" :key="index">
- <el-card :style="{ background: item.bgColor }" class="box-card-num">
- <el-row class="box-card-row" style="margin:0">
- <el-col :span="16" class="box_left">
- <p>{{ item.name }}</p>
- <p>{{ item.value }}</p>
- </el-col>
- <el-col :span="8">
- <el-image style="width:125px;height:80px" :src="item.icon" fit="cover"></el-image>
- </el-col>
- </el-row>
- <el-divider />
- <el-row class="add_bg">
- <div>
- <span>今日新增</span>
- <el-image style="width:9px;height:9px;" :src="item.addIcon"></el-image>
- <span>{{ item.addValue }}</span>
- </div>
- </el-row>
- </el-card>
- </el-col>
- </el-row>
- <el-row :gutter="10">
- <el-col :span="12" v-for="(item, index) in state.barList" :key="index">
- <el-card class="pie_bg">
- <p>{{ item.name }}</p>
- <el-divider />
- <div v-if="index == 0">
- <div ref="deviceNum_ref" id="deviceNum" />
- </div>
- <div v-else class="device_bg">
- <div class="device_item" v-for="(item, index) in state.deviceTypeList" :key="index">
- <div class="icon_bg" :id="'devicechart' + index"></div>
- <div class="title">{{ item.title }}</div>
- <div class="num" :style="{'--color':state.deviceColor[index]}">{{ item.rate }}%</div>
- </div>
- <div class="legend_bg">
- <div class="device_legend" v-for="(itemL, index) in state.deviceTypeList" :key="index">
- <span :style="{'--color':state.deviceColor[index]}"></span>
- <span>{{ itemL.title }}:</span>
- <span>{{ itemL.num}}</span>
- </div>
- </div>
- </div>
- </el-card>
- </el-col>
- </el-row>
- <!-- <el-row :gutter="10" class="top_row">
- <el-col :span="8" class="box-card_bg" v-for="(item, index) in state.jumpListData" :key="index">
- <el-card @click="jumpweb(item.type)" :style="{ background: item.bgColor }" class="box-card-num">
- <el-row class="box-card-row" style="margin:0">
- <el-col :span="16" class="box_left">
- <p :style="{ '--colorTitle': item.color }" class="jump_title">{{ item.name }}</p>
- </el-col>
- <el-col :span="8">
- <el-image style="width:125px;height:80px" :src="item.icon" fit="cover"></el-image>
- </el-col>
- </el-row>
- </el-card>
- </el-col>
- </el-row> -->
- <el-row :gutter="10">
- <el-col :span="24">
- <el-card class="box-bottom_bg">
- <p>平台架构图</p>
- <el-divider />
- <el-image class="framework" :src="home_5" fit="contain"></el-image>
- </el-card>
- </el-col>
- </el-row>
- </div>
- </template>
- <script setup name="Index" lang="ts">
- import { categoryList, productList, deviceList, deviceCategory,deviceStates,customerApi} from '@/api/home'
- import * as echarts from 'echarts'
- import { md5Encrypt } from '@/utils/jsencrypt'
- import home_1 from '@/assets/images/home/home_1.png'
- import home_2 from '@/assets/images/home/home_2.png'
- import home_3 from '@/assets/images/home/home_3.png'
- import home_4 from '@/assets/images/home/home_4.png'
- import home_5 from '@/assets/images/home/home_5.png'
- import { getName } from '@/utils/auth'
- enum TypeApi {
- tend = 'tend',
- health = 'health',
- bed = 'bed'
- }
- const deviceNum_ref = ref()
- const state = reactive({
- deviceListData: [
- {
- name: '品类数量',
- value: 0,
- addValue: 0,
- bgColor: 'linear-gradient(225deg, #F1F7FF 0%, #FFFFFF 36%, #FFFFFF 100%)',
- icon: home_1,
- addIcon: home_4
- },
- {
- name: '产品数量',
- value: 11,
- addValue: 4,
- bgColor: 'linear-gradient(225deg, #FFF6EE 0%, #FFFFFF 36%, #FFFFFF 100%)',
- icon: home_2,
- addIcon: home_4
- },
- {
- name: '设备数量',
- value: 12,
- addValue: 5,
- bgColor: 'linear-gradient(225deg, #EEFFF5 0%, #FFFFFF 36%, #FFFFFF 100%)',
- icon: home_3,
- addIcon: home_4
- }
- ],
- barList: [
- {
- name: '设备数量统计'
- },
- {
- name: '设备状态统计'
- }
- ],
- jumpListData: [
- {
- type:TypeApi.tend,
- name: '安全照护',
- bgColor: 'linear-gradient(225deg, #F1F7FF 0%, #FFFFFF 36%, #FFFFFF 100%)',
- color:'#477ec6',
- icon: home_1
- },
- {
- type:TypeApi.health,
- name: '健康监测',
- bgColor: 'linear-gradient(225deg, #FFF6EE 0%, #FFFFFF 36%, #FFFFFF 100%)',
- color: '#da8a45',
- icon: home_2
- },
- {
- type:TypeApi.bed,
- name: '数字家床',
- bgColor: 'linear-gradient(225deg, #EEFFF5 0%, #FFFFFF 36%, #FFFFFF 100%)',
- color: '#26b669',
- icon: home_3
- }
- ],
- pieOptionData: [],
- pieColor: [
- 'rgba(255, 162, 23, 1)',
- 'rgba(255, 119, 106, 1)',
- 'rgba(108, 201, 255, 1)',
- 'rgba(108, 158, 254, 1)',
- 'rgba(85, 116, 251, 1)',
- 'rgba(139, 126, 255, 1)',
- 'rgba(95, 208, 164, 1)',
- 'rgba(250, 204, 62, 1)'
- ],
- // 设备状态统计
- deviceColor:[
- 'rgba(96, 208, 164, 1)',
- 'rgba(254, 103, 86, 1)',
- 'rgba(103, 154, 255, 1)'
- ],
- deviceTypeList: [
- { title: '在线设备', num: 0, rate: 0 },
- { title: '离线设备', num: 0, rate: 0 },
- { title: '待激活设备', num: 0, rate: 0 },
- ]
- })
- // 设备数量统计图表
- const setBar1 = (dataObj:object) => {
- if (typeof dataObj === 'object' && Object.keys(dataObj).length === 0) {
- dataObj = {'设备总数': 0}
- }
- const keys = Object.keys(dataObj)
- const values = Object.values(dataObj)
- let totlaNum = 0
- const pieDataT = values.map((item,index)=>{
- totlaNum += item
- return {
- name: keys[index],
- value: item
- }
- })
- const chartDom: any = document.getElementById('deviceNum')
- const myChart: any = echarts.init(chartDom)
- // const deviceNum_refIntance = echarts.init(deviceNum_ref.value)
- myChart.setOption({
- legend: {
- backgroundColor: 'transparent',
- type: 'plain',
- show: 'true',
- height: '100%',
- left:'45%',
- // right: '1%',
- top: 0,
- bottom: 0,
- orient: 'vertical',
- itemGap: 10,
- itemWidth: 12,
- itemHeight: 12,
- icon: 'circle',
- borderRadius: 0,
- formatter: function (name) {
- // let titleList = name.split('|')
- // return `{a|${titleList[0]}}{b|${titleList[1]}}`
- const pieItem = pieDataT.find(item => item.name == name)
- return `{a|${name}:}{b|${pieItem?.value}}`
- },
- textStyle: {
- color: 'rgba(175, 187, 206, 1)',
- fontSize: 10,
- rich: {
- a: {
- minWidth: 30,
- align: 'left',
- color: 'rgba(0, 11, 25, 1)',
- fontSize: 14,
- fontWeight: 500,
- padding: [0, 0, 0, 5]
- },
- b: {
- width: 70,
- color: 'rgba(0, 11, 25, 1)',
- align: 'left',
- fontSize: 18,
- fontWeight: 'bold',
- backgroundColor: 'transparent',
- padding: [0, 0, 0, 8]
- }
- }
- }
- },
- tooltip: {
- trigger: 'item',
- formatter: '{a} <br/>{b} : {c} ({d}%)'
- },
- graphic: [
- {
- z: 9,
- type: 'text',
- left: '17.5%',
- top: '40%',
- background: 'red',
- style: {
- text: totlaNum,
- fontSize: 18,
- textAlign: 'center',
- fill: 'rgba(0, 11, 25, 1)',
- font: 'OPPOSans-B,OPPOSans',
- width: 120,
- height: 20,
- }
- },
- {
- z: 9,
- type: 'text',
- left: '17%',
- top: '52%',
- style: {
- text: '设备总数',
- fontSize: 12,
- textAlign: 'center',
- fill: 'rgba(0, 11, 25, 1)',
- width: 100,
- height: 30,
- }
- },
- ],
- series: [
- {
- name: '设备总数',
- type: 'pie',
- // roseType: 'radius',
- radius: ['55%', '95%'],
- center: ['20%', '50%'],
- label: {
- show: false,
- position: 'center',
- },
- // 数据引线
- labelLine: {
- show: false
- },
- data: pieDataT,
- animationEasing: 'cubicInOut',
- animationDuration: 100
- }
- ]
- }, true)
- }
- // 设备状态统计
- const setCommonOption = (serveRate: number,deviceNum:number, barColor: string) => {
- let option = {
- graphic: [
- {
- z: 9,
- type: 'text',
- left: 'center',
- top: 'center',
- style: {
- text: deviceNum+'个',
- fontSize: 18,
- textAlign: 'center',
- fill: 'rgba(0, 11, 25, 1)',
- font: 'OPPOSans-B,OPPOSans',
- width: 50,
- height: 20,
- }
- }
- ],
- series: [
- {
- name: '服务覆盖率',
- type: 'pie',
- radius: ['72%', '72%'],
- center: ['50%', '50%'],
- startAngle: 270,
- avoidLabelOverlap: false,
- label: {
- show: false
- },
- z: 3,
- data: [
- {
- value: serveRate,
- name: '服务覆盖率',
- itemStyle: {
- borderWidth: 15,
- borderCap: 'round',
- borderColor: barColor
- },
- },
- {
- value: 100 - serveRate,
- name: '占位背景',
- },
- ]
- },
- {
- name: '占位背景',
- type: 'pie',
- radius: ['72%', '72%'],
- center: ['50%', '50%'],
- startAngle: 270,
- avoidLabelOverlap: false,
- label: {
- show: false
- },
- data: [
- {
- value: 1,
- name: '占位背景',
- itemStyle: {
- borderWidth: 15,
- borderColor: 'rgba(230, 230, 230, 1)'
- },
- }
- ]
- },
- ]
- }
- return option
- }
- interface deviceObj {
- offline: number
- online: number
- unactivated: number
- }
- const setBar2 = (dataObj:deviceObj) => {
- setTimeout(() => {
- let deviceTotalNum = dataObj.offline + dataObj.online +dataObj.unactivated
- const unactivatedRate = ((dataObj.unactivated / deviceTotalNum)*100).toFixed(2)
- state.deviceTypeList[0].num = dataObj.online
- state.deviceTypeList[0].rate = parseFloat(((dataObj.online / deviceTotalNum)*100).toFixed(2)) || 0
- state.deviceTypeList[1].num = dataObj.offline
- state.deviceTypeList[1].rate = parseFloat(((dataObj.offline / deviceTotalNum)*100).toFixed(1)) || 0
- state.deviceTypeList[2].num = dataObj.unactivated
- state.deviceTypeList[2].rate = parseFloat(unactivatedRate) || 0
- console.log('state.deviceTypeList:')
- console.log(state.deviceTypeList)
- const chartDom1: any = document.getElementById('devicechart0')
- const chartDom2: any = document.getElementById('devicechart1')
- const chartDom3: any = document.getElementById('devicechart2')
- const myChart1: any = echarts.init(chartDom1)
- const myChart2: any = echarts.init(chartDom2)
- const myChart3: any = echarts.init(chartDom3)
- myChart1.setOption(setCommonOption(state.deviceTypeList[0].rate,state.deviceTypeList[0].num,state.deviceColor[0]))
- myChart2.setOption(setCommonOption(state.deviceTypeList[1].rate,state.deviceTypeList[1].num,state.deviceColor[1]))
- myChart3.setOption(setCommonOption(state.deviceTypeList[2].rate,state.deviceTypeList[2].num,state.deviceColor[2]))
- }, 100)
- }
- const getDataList = async () => {
- const categoryData = await categoryList({
- data:{},
- requestId:''
- })
- const productData = await productList({
- data:{},
- requestId:''
- })
- const deviceData = await deviceList({
- data:{},
- requestId:''
- })
- state.deviceListData[0].value = categoryData.data && categoryData.data.categoryAllNum
- state.deviceListData[0].addValue = categoryData.data && categoryData.data.categoryTodayNum
- state.deviceListData[1].value = productData.data && productData.data.productAllNum
- state.deviceListData[1].addValue = productData.data && productData.data.productTodayNum
- state.deviceListData[2].value = deviceData.data && deviceData.data.viceAllNum
- state.deviceListData[2].addValue = deviceData.data && deviceData.data.deviceTodayNum
- const deviceCategoryData = await deviceCategory({
- data:{},
- requestId:''
- })
- const deviceStatesData = await deviceStates({
- data:{},
- requestId:''
- })
- setTimeout(() => {
- setBar1(deviceCategoryData.data)
- setBar2(deviceStatesData.data)
- }, 200)
- }
- const goTarget = (url: string) => {
- window.open(url, '__blank')
- }
- const jumpweb = async (type: any) => {
- let md5Txt = md5Encrypt(String(getName()).toLowerCase())
- let paraStr = `user=${getName()}&token=${md5Txt}`
- switch (type) {
- case TypeApi.tend:
- {
- window.open(`https://web.poteviohealth.com/zhylsafecase/index.html?${paraStr}`,'_blank')
- }
- break
- case TypeApi.health:
- {
- let customerData = await customerApiF(md5Txt)
- if(customerData['status'] == 0) {
- // https://web.poteviohealth.com/r/daping/health/index.html?customerId=160
- window.open(`https://web.poteviohealth.com/r/daping/health/index.html?customerId=${customerData['customerId']}`,'_blank')
- }else {
- ElMessage.error('跳转出错:'+ JSON.stringify(customerData))
- }
- }
- break
- case TypeApi.bed:
- {
- window.open(`http://web.poteviohealth.com/boss/daping/data.html?${paraStr}`,'_blank')
- }
- break
- default:
- break
- }
- }
- const customerApiF = async (md5Txt: string) => {
- const customerData = await customerApi({
- command:'customerloginiot',
- account:'iot'+getName(),
- password: md5Txt,
- terminalType: 'health'
- })
- return customerData
- }
- onMounted(() => {
- getDataList()
- })
- </script>
- <style scoped lang="scss">
- .home {
- font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 13px;
- color: #676a6c;
- overflow-x: hidden;
- .top_row {
- margin-bottom: 15px;
- }
- .box-card-num {
- width: 100%;
- height: 154px;
- .box-card-row {
- width: 100%;
- height: 80px;
- .box_left {
- width: 100%;
- height: 100%;
- p:nth-of-type(1) {
- height: 10px;
- font-size: 16px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #A4ACB4;
- }
- p:nth-of-type(2) {
- font-size: 34px;
- font-family: PingFangSC, PingFang SC;
- font-weight: 600;
- color: #000B19;
- }
- .jump_title {
- margin-top: 40px;
- color: var(--colorTitle) !important;
- padding-left: 55px;
- box-sizing: border-box;
- font-size: 24px !important;
- font-weight: 500 !important;
- }
- }
- }
- .el-divider--horizontal {
- margin: 12px 0;
- }
- .add_bg {
- width: 100%;
- height: 65px;
- span:nth-of-type(1) {
- font-size: 14px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #A4ACB4;
- margin-right: 3px;
- }
- span:nth-of-type(2) {
- font-size: 14px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #03B32A;
- margin-left: 3px;
- }
- }
- }
- .pie_bg {
- width: 100%;
- height: 255px;
- p {
- font-size: 16px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #000B19;
- }
- .el-divider--horizontal {
- margin: 12px 0;
- }
- #deviceNum {
- width: 100%;
- height: 170px;
- }
- .device_bg {
- width: 100%;
- height: 170px;
- display: flex;
- .device_item {
- width: 25%;
- height: 100%;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- .icon_bg {
- width: 100%;
- height: 75%;
- }
- .title {
- font-size: 12px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #000B19;
- }
- .num {
- font-size: 13px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: bolder;
- color: var(--color);
- }
- }
- .legend_bg {
- width: 25%;
- height: 100%;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- .device_legend {
- width: 100%;
- height: 23%;
- span:nth-of-type(1) {
- display: inline-block;
- width: 12px;
- height: 12px;
- border-radius: 6px;
- background-color: var(--color);
- margin-right: 8px;
- }
- span:nth-of-type(2) {
- font-size: 14px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #000B19;
- margin-right: 8px;
- }
- span:nth-of-type(3) {
- font-size: 18px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: bold;
- color: #000B19;
- }
- }
- }
- }
- }
- .el-row:nth-of-type(3) {
- margin-top: 15px;
- }
- .el-row:nth-of-type(4) {
- margin-top: 15px;
- .box-bottom_bg {
- width: 100%;
- min-height: 337px;
- p {
- font-size: 16px;
- font-family: SourceHanSansCN, SourceHanSansCN;
- font-weight: 500;
- color: #000B19;
- }
- .el-divider--horizontal {
- margin: 12px 0;
- }
- .el-image {
- width: 100%;
- height: 400px;
- }
- }
- }
- blockquote {
- padding: 10px 20px;
- margin: 0 0 20px;
- font-size: 17.5px;
- border-left: 5px solid #eee;
- }
- hr {
- margin-top: 20px;
- margin-bottom: 20px;
- border: 0;
- border-top: 1px solid #eee;
- }
- .col-item {
- margin-bottom: 20px;
- }
- ul {
- padding: 0;
- margin: 0;
- }
- ul {
- list-style-type: none;
- }
- h4 {
- margin-top: 0px;
- }
- h2 {
- margin-top: 10px;
- font-size: 26px;
- font-weight: 100;
- }
- p {
- margin-top: 10px;
- b {
- font-weight: 700;
- }
- }
- .update-log {
- ol {
- display: block;
- list-style-type: decimal;
- margin-block-start: 1em;
- margin-block-end: 1em;
- margin-inline-start: 0;
- margin-inline-end: 0;
- padding-inline-start: 40px;
- }
- }
- }</style>
|