feat:更新飞渡ac.min.js
After Width: | Height: | Size: 7.1 KiB |
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>进入后台</title>
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
|
||||||
|
<stop stop-color="#FFFFFF" offset="0%"></stop>
|
||||||
|
<stop stop-color="#C4EEFF" offset="100%"></stop>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
|
||||||
|
<stop stop-color="#F7F7F7" offset="0%"></stop>
|
||||||
|
<stop stop-color="#F7F7F7" offset="100%"></stop>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="智慧化工园区/封闭园区-首页" transform="translate(-1476.000000, -18.000000)" fill="url(#linearGradient-2)" fill-rule="nonzero">
|
||||||
|
<g id="进入后台" transform="translate(1476.000000, 18.000000)">
|
||||||
|
<g id="编组" transform="translate(1.000000, 2.000000)">
|
||||||
|
<path d="M13.5997167,15.8663833 C13.9078191,15.8732724 14.1539931,16.1250122 14.1539931,16.4331917 C14.1539931,16.7413711 13.9078191,16.993111 13.5997167,17 L3.4,17 C3.09189753,16.993111 2.84572355,16.7413711 2.84572355,16.4331917 C2.84572355,16.1250122 3.09189753,15.8732724 3.4,15.8663833 L13.6,15.8663833 L13.5997167,15.8663833 Z M14.1663833,0 C15.7301,0 17,1.18546666 17,2.6435 L17,12.0889833 C16.9977333,13.5473 15.7278333,14.7324834 14.1663833,14.7324834 L2.83333334,14.7324834 C1.27245,14.7327667 0,13.5475833 0,12.0892667 L0,2.64378334 C0,1.18546666 1.27216666,0 2.83361666,0 L14.1666667,0 L14.1663833,0 Z M14.1663833,1.13361666 L2.83333334,1.13361666 C1.89521668,1.13361666 1.13333334,1.81078332 1.13333334,2.64378334 L1.13333334,12.0889833 C1.13333334,12.9217 1.89521668,13.59915 2.83333334,13.59915 L14.1658167,13.59915 C15.1042167,13.59915 15.8661003,12.9217 15.8661003,12.0889833 L15.8661003,2.64378334 C15.8666667,1.81106666 15.1045,1.13333334 14.1666667,1.13333334 L14.1663833,1.13361666 Z M9.60925,5.15383334 L9.71295,5.21333334 C9.9042,5.32978334 9.97248334,5.58733334 9.86623334,5.79218334 L8.2229,8.8485 C8.12345,9.03975 7.90443334,9.1171 7.71856666,9.03351666 L7.67351666,9.00971666 L7.67465,9.00971666 L7.56981666,8.95021666 C7.37856666,8.83348332 7.31028332,8.57621666 7.41653334,8.37108334 L9.05986666,5.31505 C9.1715,5.11246666 9.41516666,5.04078334 9.60925,5.15355 L9.60925,5.15383334 Z M4.66026666,5.23146666 C4.80638892,5.0697265 5.05550469,5.05582354 5.21871666,5.2003 L5.25668334,5.23713334 C5.40741668,5.40146668 5.41591668,5.65986668 5.28331666,5.83496666 L5.25271666,5.87123334 L4.1225,7.08333334 L5.26065,8.296 C5.4243111,8.4773971 5.42406623,8.75324375 5.26008334,8.93435 C5.10708334,9.09868334 4.8654,9.10945 4.70078334,8.96665 L4.66678334,8.93378334 L3.24076666,7.4103 C3.08768133,7.23724923 3.07485782,6.98124945 3.20988334,6.79376666 L3.24105,6.75608334 L4.66055,5.2309 L4.66026666,5.23146666 Z M11.7402,5.23203334 C11.8861351,5.06967116 12.1356986,5.05537785 12.2992167,5.20001666 L12.3332167,5.23288334 L13.75895,6.76543334 C13.8411167,6.84675 13.88645,6.96263334 13.8827667,7.08276666 C13.8844667,7.18845 13.8516,7.29045 13.7915333,7.37233334 L13.75895,7.41143334 L12.3332167,8.93293334 C12.1793667,9.09981668 11.9402333,9.11086668 11.7739167,8.96636666 L11.7370833,8.9301 C11.5874049,8.76280265 11.575693,8.51342237 11.7090333,8.33283334 L11.7396333,8.29656666 L12.8692833,7.08276666 L11.7396333,5.87066666 C11.575933,5.68917628 11.5761778,5.41323293 11.7402,5.23203334 Z" id="形状"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.9 KiB |
|
@ -0,0 +1,74 @@
|
||||||
|
<div class="center-right d-flex">
|
||||||
|
<div class="box-content height-auto">
|
||||||
|
<title-component :bg-size="'large'" :imgSrc="imgPowerSrc">
|
||||||
|
企业消防力量分布
|
||||||
|
</title-component>
|
||||||
|
<div class="margin-top-30 d-flex flex-wrap">
|
||||||
|
<div class="d-flex wd-100" v-for="item in powerList">
|
||||||
|
<div v-for="single in item" class="power-item d-flex">
|
||||||
|
<div class="icon-style" v-if="single.label">
|
||||||
|
<img :src="iconImg3" alt="">
|
||||||
|
</div>
|
||||||
|
<div v-if="single.label">
|
||||||
|
<div>
|
||||||
|
<b>
|
||||||
|
{{ single.num }}
|
||||||
|
</b>
|
||||||
|
</div>
|
||||||
|
<div class="text-style">{{ single.label }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content flex-0 height-auto">
|
||||||
|
<title-component :bg-size="'large'" @changeMore="changeMore('large')" :show-more="true" :imgSrc="imgAlertSrc">
|
||||||
|
全场重点消防监控报警
|
||||||
|
</title-component>
|
||||||
|
<div class="d-flex height-auto margin-top-30">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="charts-box">
|
||||||
|
<div class="text">
|
||||||
|
<div class="count">{{ count }}%</div>
|
||||||
|
设备在线
|
||||||
|
</div>
|
||||||
|
<el-progress type="circle" :width="172" define-back-color="rgba(255,255,255,0.16)" :format="textFormat"
|
||||||
|
:stroke-width="16" :percentage="count" :color="colors"></el-progress>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex margin-top-23 padding-0-15">
|
||||||
|
<div class="flex-1 text-center green-text font-size-14">
|
||||||
|
在线监测 50
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 text-center font-size-14">
|
||||||
|
总监测点 63
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 d-flex flex-direction-column">
|
||||||
|
<div class="static margin-bottom-16">
|
||||||
|
<div class="border l-t"></div>
|
||||||
|
<div class="border r-t"></div>
|
||||||
|
<div class="border r-b"></div>
|
||||||
|
<div class="border l-b"></div>
|
||||||
|
<span><i class="green-cycle"></i>已处理报警</span><span class="count">75</span>
|
||||||
|
</div>
|
||||||
|
<div class="static margin-bottom-16">
|
||||||
|
<div class="border l-t"></div>
|
||||||
|
<div class="border r-t"></div>
|
||||||
|
<div class="border r-b"></div>
|
||||||
|
<div class="border l-b"></div>
|
||||||
|
<span><i class="orange-cycle"></i>未处理报警</span><span class="count">75</span>
|
||||||
|
</div>
|
||||||
|
<div class="static margin-bottom-16">
|
||||||
|
<div class="border l-t"></div>
|
||||||
|
<div class="border r-t"></div>
|
||||||
|
<div class="border r-b"></div>
|
||||||
|
<div class="border l-b"></div>
|
||||||
|
<span><i class="red-cycle"></i>逾期处理</span><span class="count">75</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,104 @@
|
||||||
|
import {Component, Emit, Vue} from 'vue-property-decorator';
|
||||||
|
import template from "./centerSide.component.html"
|
||||||
|
import TitleComponent from "@/components/title.component.vue"
|
||||||
|
|
||||||
|
import("@/assets/style/pageCommon.component.scss")
|
||||||
|
|
||||||
|
|
||||||
|
Component.registerHooks([
|
||||||
|
'beforeRouteLeave',
|
||||||
|
]);
|
||||||
|
@Component({
|
||||||
|
template,
|
||||||
|
components: {
|
||||||
|
TitleComponent,
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class CenterSideComponent extends Vue {
|
||||||
|
//标题图片
|
||||||
|
imgSrc = require("@/assets/icons/png/env/env-title-icon.png");
|
||||||
|
imgPowerSrc = require("@/assets/icons/png/power-icon.png");
|
||||||
|
imgAlertSrc = require("@/assets/icons/png/alert-icon.png");
|
||||||
|
iconImg3 = require("@/assets/img/env/count.png");
|
||||||
|
count = 0
|
||||||
|
public timer:any;
|
||||||
|
public colors = [
|
||||||
|
{color: '#FF5959', percentage: 20},
|
||||||
|
{color: '#FF5959', percentage: 40},
|
||||||
|
{color: '#FFA900', percentage: 60},
|
||||||
|
{color: '#80ED30', percentage: 80},
|
||||||
|
{color: '#80ED30', percentage: 100}
|
||||||
|
];
|
||||||
|
powerList = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: '消防人员(人)',
|
||||||
|
num: 34
|
||||||
|
},{
|
||||||
|
label: '消防车辆(辆)',
|
||||||
|
num: 4
|
||||||
|
},{
|
||||||
|
label: '消防设施(个)',
|
||||||
|
num: 54
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[{
|
||||||
|
label: '火灾报警点(个)',
|
||||||
|
num: 20
|
||||||
|
},{
|
||||||
|
label: '应急物资(套)',
|
||||||
|
num: 340
|
||||||
|
},{
|
||||||
|
label: '重大危险源(个)',
|
||||||
|
num: 2
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
label: '储罐(个)',
|
||||||
|
num: 24
|
||||||
|
},{
|
||||||
|
label: '重大危险源(个)',
|
||||||
|
num: 4
|
||||||
|
},{
|
||||||
|
label: '',
|
||||||
|
num: 0
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.timer = setInterval(()=>{
|
||||||
|
|
||||||
|
this.getCount(80)
|
||||||
|
},4000)
|
||||||
|
}
|
||||||
|
public textFormat(data){
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
public getCount(data){
|
||||||
|
this.count = 0;
|
||||||
|
setTimeout(()=>{
|
||||||
|
const timer = setInterval(()=>{
|
||||||
|
if(this.count<data){
|
||||||
|
this.count++
|
||||||
|
}else{
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
},20)
|
||||||
|
},400)
|
||||||
|
|
||||||
|
}
|
||||||
|
@Emit('changeMore')
|
||||||
|
changeMore(e){
|
||||||
|
|
||||||
|
}
|
||||||
|
beforeDestroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<div class="env-left left-part">
|
||||||
|
<div class="box-content flex-0 height-auto">
|
||||||
|
<title-component :imgSrc="imgDutySrc">
|
||||||
|
今日消防值班人员
|
||||||
|
</title-component>
|
||||||
|
<div class="plan-card margin-top-10">
|
||||||
|
<div class="border l-t"></div>
|
||||||
|
<div class="border r-t"></div>
|
||||||
|
<div class="border r-b"></div>
|
||||||
|
<div class="border l-b"></div>
|
||||||
|
<p class="margin-bottom-13">带班领导陈远航 139308897887</p>
|
||||||
|
<ScrollBoxComponent :id="'dutyBox'" class="duty-box" :speed="0.15">
|
||||||
|
<ul class="plan">
|
||||||
|
<li :key="i" v-for="(item,i) in dutyList">
|
||||||
|
<div class="d-flex flex-align-center">
|
||||||
|
<img src="~@/assets/img/default-icon.png" alt="">
|
||||||
|
<span class="duty-name-box">{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="tel-box">{{ item.tel }}</span>
|
||||||
|
<span>{{ item.job }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</ScrollBoxComponent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<title-component class="margin-top-30" :imgSrc="imgCarSrc">
|
||||||
|
车辆信息
|
||||||
|
</title-component>
|
||||||
|
<div class="plan-head">
|
||||||
|
<span class="span-item">车辆类型</span>
|
||||||
|
<span class="span-item">备战</span>
|
||||||
|
<span class="span-item">巡检</span>
|
||||||
|
<span class="span-item">故障</span>
|
||||||
|
<span class="span-item">保养</span>
|
||||||
|
<span class="span-item">合计</span>
|
||||||
|
</div>
|
||||||
|
<ScrollBoxComponent :id="'carBox'" class="car-box" :speed="0.15">
|
||||||
|
<div class="plan-head-tbody">
|
||||||
|
<div class="tr" :key="i" v-for="(item,i) in tableData">
|
||||||
|
<span class="span-item">{{ item.title }}</span>
|
||||||
|
<span class="span-item">{{ item.bz }}</span>
|
||||||
|
<span class="span-item">{{ item.xj }}</span>
|
||||||
|
<span class="span-item">{{ item.gz }}</span>
|
||||||
|
<span class="span-item">{{ item.by }}</span>
|
||||||
|
<span class="span-item">{{ item.total }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollBoxComponent>
|
||||||
|
</div>
|
||||||
|
<div class="box-content flex-0" style="height: 300px">
|
||||||
|
<title-component class="margin-top-30" @changeMore="changeMore('small')" :show-more="true" :imgSrc="imgPointSrc">
|
||||||
|
重点区域火灾报警点位
|
||||||
|
</title-component>
|
||||||
|
<div class="fire-point d-flex flex-wrap margin-top-16 margin-bottom-20">
|
||||||
|
<ScrollBoxComponent :id="'eqBox'" class="eqBox" :speed="0.15">
|
||||||
|
<div>
|
||||||
|
<div class="fire-point-item d-flex" v-for="item in eqList">
|
||||||
|
<div class="fire-point-item-item bg-gyay">{{item.label}}</div>
|
||||||
|
<div class="fire-point-item-item" :class="item.status === 0?'red-text':'green-text'">{{item.status === 0?'报警':'正常'}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollBoxComponent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,481 @@
|
||||||
|
import {Component, Emit, Prop, Vue} from 'vue-property-decorator';
|
||||||
|
import template from "./leftSide.component.html"
|
||||||
|
|
||||||
|
|
||||||
|
import TitleComponent from "@/components/title.component.vue"
|
||||||
|
import WarningListComponent from "@/components/warningList.component.vue"
|
||||||
|
import ScrollBoxComponent from "@/components/scrollBox.component.vue"
|
||||||
|
import * as turf from '@turf/turf'
|
||||||
|
import Mock from "mockjs"
|
||||||
|
import moment from "moment"
|
||||||
|
|
||||||
|
import("@/assets/style/pageCommon.component.scss")
|
||||||
|
|
||||||
|
|
||||||
|
Component.registerHooks([
|
||||||
|
'beforeRouteLeave',
|
||||||
|
]);
|
||||||
|
@Component({
|
||||||
|
template,
|
||||||
|
components: {
|
||||||
|
TitleComponent,
|
||||||
|
WarningListComponent,
|
||||||
|
ScrollBoxComponent
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class LeftSideComponent extends Vue {
|
||||||
|
//传入的报警信息详情
|
||||||
|
@Prop({
|
||||||
|
default: ()=> {
|
||||||
|
return {
|
||||||
|
"typeName": "火灾",
|
||||||
|
"content": "北京汉邦唐化工厂区发生火灾",
|
||||||
|
"levelName": "二级",
|
||||||
|
"levelClass": "level-2-text",
|
||||||
|
"levelClassIcon": "level-2",
|
||||||
|
"time": "2023-05-15 15:21:35",
|
||||||
|
"address": "工厂厂房",
|
||||||
|
"reporter": "蒋丽",
|
||||||
|
"tableHeader": [
|
||||||
|
{
|
||||||
|
"prop": "name",
|
||||||
|
"label": "摄像头名称"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prop": "type",
|
||||||
|
"label": "类型"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prop": "distance",
|
||||||
|
"label": "距离 (m)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tableData": [
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "10",
|
||||||
|
"name": "1号摄像头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "20",
|
||||||
|
"name": "2号摄像头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "22",
|
||||||
|
"name": "3号摄像头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "10",
|
||||||
|
"name": "4号摄像头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "20",
|
||||||
|
"name": "5号摄像头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "简型摄像头",
|
||||||
|
"distance": "22",
|
||||||
|
"name": "6号摄像头"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "火灾爆炸",
|
||||||
|
"info": "北京汉邦唐化工厂区发生火灾",
|
||||||
|
"level": "1",
|
||||||
|
"type": "fire",
|
||||||
|
"tel": 13231475537,
|
||||||
|
"id": "110000197911038403",
|
||||||
|
"position": [
|
||||||
|
13312990.72,
|
||||||
|
4098613.12,
|
||||||
|
0.51
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) info!: any;
|
||||||
|
//标题左侧图标
|
||||||
|
imgSrc = require("@/assets/icons/png/env/env-title-icon.png");
|
||||||
|
imgDutySrc = require("@/assets/icons/png/duty-icon.png");
|
||||||
|
imgCarSrc = require("@/assets/icons/png/car-icon.png");
|
||||||
|
imgPointSrc = require("@/assets/icons/png/point-icon.png");
|
||||||
|
|
||||||
|
currentCompany = false
|
||||||
|
popObj: any = {
|
||||||
|
popTitle: '报警记录',
|
||||||
|
type: '',
|
||||||
|
title: '风险点异常',
|
||||||
|
info: '',
|
||||||
|
time: '',
|
||||||
|
address: '',
|
||||||
|
level: '',
|
||||||
|
typeName: "",
|
||||||
|
reporter: "",
|
||||||
|
tel: "",
|
||||||
|
position: [],
|
||||||
|
content: "",
|
||||||
|
typeId: "",
|
||||||
|
id: ''
|
||||||
|
|
||||||
|
}
|
||||||
|
typeList = [
|
||||||
|
{
|
||||||
|
label: '气体泄露',
|
||||||
|
value: 'normal',
|
||||||
|
level: 2,
|
||||||
|
id: 1
|
||||||
|
}, {
|
||||||
|
label: '火灾爆炸',
|
||||||
|
value: 'fire',
|
||||||
|
level: 1,
|
||||||
|
id: 2
|
||||||
|
}, {
|
||||||
|
label: '气液泄露',
|
||||||
|
value: 'normal',
|
||||||
|
level: 1,
|
||||||
|
id: 3
|
||||||
|
}, {
|
||||||
|
label: '安全事故',
|
||||||
|
value: 'normal',
|
||||||
|
level: 2,
|
||||||
|
id: 4
|
||||||
|
}, {
|
||||||
|
label: '自然灾害',
|
||||||
|
value: 'normal',
|
||||||
|
level: 3,
|
||||||
|
id: 5
|
||||||
|
},
|
||||||
|
]
|
||||||
|
eqList =[
|
||||||
|
{
|
||||||
|
label:'乙烯装置01-Y-001',
|
||||||
|
status:1,
|
||||||
|
},{
|
||||||
|
label:'乙烯装置02-W-098',
|
||||||
|
status:0,
|
||||||
|
},{
|
||||||
|
label:'芳烃装置03-R-012',
|
||||||
|
status:1,
|
||||||
|
},{
|
||||||
|
label:'硝基苯胺04-Q-034',
|
||||||
|
status:0,
|
||||||
|
},{
|
||||||
|
label:'硝基苯胺04-T-001',
|
||||||
|
status:1,
|
||||||
|
},{
|
||||||
|
label:'邻苯甲酚09-Y-129',
|
||||||
|
status:0,
|
||||||
|
},{
|
||||||
|
label:'二氯苯胺10-Y-09',
|
||||||
|
status:0,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
levelClass = 'level-1';
|
||||||
|
levelName = '一级';
|
||||||
|
level = 1;
|
||||||
|
cardText = 'level-1-text';
|
||||||
|
dutyList = [
|
||||||
|
{name:'刘月明',tel:'139308897887',job:'指挥员'},
|
||||||
|
{name:'王建民',tel:'139308897887',job:'指挥员'},
|
||||||
|
{name:'李璇',tel:'139308897887',job:'指挥员'},
|
||||||
|
{name:'刘月明',tel:'139308897887',job:'指挥员'},
|
||||||
|
{name:'王建民',tel:'139308897887',job:'指挥员'},
|
||||||
|
{name:'李璇',tel:'139308897887',job:'指挥员'}
|
||||||
|
]
|
||||||
|
tableData = [
|
||||||
|
{
|
||||||
|
title: '水罐消防车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '2',
|
||||||
|
gz: '0',
|
||||||
|
by: '0',
|
||||||
|
total: '3',
|
||||||
|
}, {
|
||||||
|
title: '抢险救援车',
|
||||||
|
bz: '2',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
}, {
|
||||||
|
title: '干粉泡沫联用车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '2',
|
||||||
|
gz: '0',
|
||||||
|
by: '0',
|
||||||
|
total: '3',
|
||||||
|
}, {
|
||||||
|
title: '泡沫运输车',
|
||||||
|
bz: '2',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
},{
|
||||||
|
title: '重型泡沫消防车',
|
||||||
|
bz: '2',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
},{
|
||||||
|
title: '举高喷射消防车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '1',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
},{
|
||||||
|
title: '化学洗消消防车',
|
||||||
|
bz: '3',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '5',
|
||||||
|
},{
|
||||||
|
title: '大跨度消防车',
|
||||||
|
bz: '0',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '2',
|
||||||
|
},{
|
||||||
|
title: '干粉消防车',
|
||||||
|
bz: '0',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '2',
|
||||||
|
},{
|
||||||
|
title: '云梯消防车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '0',
|
||||||
|
gz: '1',
|
||||||
|
by: '1',
|
||||||
|
total: '3',
|
||||||
|
},{
|
||||||
|
title: '槽罐车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '0',
|
||||||
|
gz: '2',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
},{
|
||||||
|
title: '多功能救护车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '0',
|
||||||
|
gz: '2',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
},{
|
||||||
|
title: '后勤保障车',
|
||||||
|
bz: '1',
|
||||||
|
xj: '0',
|
||||||
|
gz: '2',
|
||||||
|
by: '1',
|
||||||
|
total: '4',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
tableDataExpert = [
|
||||||
|
{
|
||||||
|
person: '黄勇军, 程宇航,蔡宝惠',
|
||||||
|
area: '火灾救援',
|
||||||
|
checked: false,
|
||||||
|
}, {
|
||||||
|
person: '林子涵,吴琳芳,梁博雅',
|
||||||
|
area: '医疗救助',
|
||||||
|
checked: false,
|
||||||
|
}, {
|
||||||
|
person: '陶春华,邓思琪,张锐毅',
|
||||||
|
area: '医疗组',
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
tableDataVicinity = [
|
||||||
|
{
|
||||||
|
position: '人民广场东北方向…',
|
||||||
|
distance: '10',
|
||||||
|
name: '一号站',
|
||||||
|
checked: false,
|
||||||
|
}, {
|
||||||
|
position: '人民广场西南方向…',
|
||||||
|
distance: '20',
|
||||||
|
name: '四号站',
|
||||||
|
checked: false,
|
||||||
|
}, {
|
||||||
|
position: '人民广场西北方向…',
|
||||||
|
distance: '30',
|
||||||
|
name: '二号站',
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// 当前进度条
|
||||||
|
active = 1
|
||||||
|
|
||||||
|
get dataList() {
|
||||||
|
return this.$store.state.warningList.filter(item => item.model === 'eme')
|
||||||
|
}
|
||||||
|
|
||||||
|
//下一步操作
|
||||||
|
nextStep() {
|
||||||
|
if (this.active < 3) {
|
||||||
|
this.active++
|
||||||
|
}
|
||||||
|
this.gotoNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Emit('gotoNext')
|
||||||
|
gotoNext() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
changeLevel(type) {
|
||||||
|
if (type === 'up') {
|
||||||
|
if (this.level === 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.level--
|
||||||
|
|
||||||
|
} else if (type === 'down') {
|
||||||
|
if (this.level === 4) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.level++
|
||||||
|
}
|
||||||
|
const nameList = {
|
||||||
|
1: '一级',
|
||||||
|
2: '二级',
|
||||||
|
3: '三级',
|
||||||
|
4: '四级',
|
||||||
|
}
|
||||||
|
this.levelName = nameList[this.level]
|
||||||
|
this.levelClass = `level-${this.level}`
|
||||||
|
this.cardText = `level-${this.level}-text`
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(val, type) {
|
||||||
|
if (type === 'typeName') {
|
||||||
|
const find = this.typeList.find(item => item.id == val) as any
|
||||||
|
this.popObj.level = find.level
|
||||||
|
this.popObj.title = find.label
|
||||||
|
this.popObj.type = find.value
|
||||||
|
}
|
||||||
|
this.popObj[type] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
//展示告警信息
|
||||||
|
showWaring(item) {
|
||||||
|
const levelMap = {
|
||||||
|
1:'一级',
|
||||||
|
2:'二级',
|
||||||
|
3:'三级',
|
||||||
|
4:'四级',
|
||||||
|
}
|
||||||
|
const levelClassMap = {
|
||||||
|
4:'blue',
|
||||||
|
3:'yellow',
|
||||||
|
2:'orange',
|
||||||
|
1:'red',
|
||||||
|
}
|
||||||
|
this.getItem(Object.assign(item,{
|
||||||
|
level:item.level,
|
||||||
|
levelClass:levelClassMap[item.level],
|
||||||
|
levelName:levelMap[item.level],
|
||||||
|
equipment:'园区2号监测点',
|
||||||
|
tableHeader:[
|
||||||
|
{
|
||||||
|
'prop': 'alarmSubject',
|
||||||
|
'label': '告警主体',
|
||||||
|
'width': '90px',
|
||||||
|
}, {
|
||||||
|
'prop': 'COD',
|
||||||
|
'label': 'COD',
|
||||||
|
}, {
|
||||||
|
'prop': 'standard',
|
||||||
|
'label': '标准值',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableData: [{
|
||||||
|
'alarmSubject': '排放量',
|
||||||
|
'COD': '456m<sup>3</sup>',
|
||||||
|
'standard': '466m<sup>3</sup>',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放浓度',
|
||||||
|
'COD': '2.6mg/L',
|
||||||
|
'standard': '2.5mg/L',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放时间',
|
||||||
|
'COD': '2023.3.31 05:03:45',
|
||||||
|
'standard': '8:00-22:00',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放浓度',
|
||||||
|
'COD': '2.6mg/L',
|
||||||
|
'standard': '2.5mg/L',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放时间',
|
||||||
|
'COD': '2023.3.31 05:03:45',
|
||||||
|
'standard': '8:00-22:00',
|
||||||
|
}]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
//点击告警信息
|
||||||
|
@Emit()
|
||||||
|
getItem(item) {
|
||||||
|
// console.log('item', item)
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
changeClose() {
|
||||||
|
console.log(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
addManual() {
|
||||||
|
this.currentCompany = true
|
||||||
|
}
|
||||||
|
|
||||||
|
submitWaring() {
|
||||||
|
this.popObj.id = Mock.mock("@id");
|
||||||
|
if (this.popObj.type === 'normal') {
|
||||||
|
this.popObj.position = turf.randomPosition([
|
||||||
|
13312995.84,
|
||||||
|
4098177.2800000003,
|
||||||
|
13313096.96,
|
||||||
|
4098754.88,
|
||||||
|
]);
|
||||||
|
} else if (this.popObj.type === 'fire') {
|
||||||
|
this.popObj.position = [13312990.72, 4098613.12, 0.51]
|
||||||
|
}
|
||||||
|
this.popObj.time = moment().subtract(0, "days").format("YYYY-MM-DD HH:mm:ss")
|
||||||
|
|
||||||
|
this.$store.commit("upDateWaringList", [this.popObj])
|
||||||
|
this.currentCompany = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//点击点位
|
||||||
|
@Emit('changePoint')
|
||||||
|
changePoint(item) {
|
||||||
|
console.log(item)
|
||||||
|
//
|
||||||
|
}
|
||||||
|
//点击点位
|
||||||
|
@Emit('changeMore')
|
||||||
|
changeMore(item) {
|
||||||
|
console.log(item)
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<div class="env-right">
|
||||||
|
<div class="box-content">
|
||||||
|
<title-component :imgSrc="imgMsgSrc">
|
||||||
|
报警信息
|
||||||
|
</title-component>
|
||||||
|
<div class="margin-top-30 waring-list-con">
|
||||||
|
<warning-list-component @getItem="showWaring" :data-list="dataList"></warning-list-component>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content margin-top-20 flex-0 height-auto">
|
||||||
|
<title-component @changeMore="changeMore('video')" :show-more="true" :imgSrc="imgVideoSrc">
|
||||||
|
全场重点消防监控
|
||||||
|
</title-component>
|
||||||
|
<div class="margin-top-12">2#氧化反应器R-2222</div>
|
||||||
|
<div class="img-box margin-top-12" @click="openPopVideo">
|
||||||
|
<img width="100%" src="~@/assets/img/index_video_1.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="margin-top-12">4#氧化反应器R-2224</div>
|
||||||
|
<div @click="openPopVideo" class="img-box margin-top-12">
|
||||||
|
<img width="100%" src="~@/assets/img/index_video_2.png" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,102 @@
|
||||||
|
import {Component, Emit, Vue} from 'vue-property-decorator';
|
||||||
|
import template from "./rightSide.component.html"
|
||||||
|
import TitleComponent from "@/components/title.component.vue"
|
||||||
|
import WarningListComponent from "@/components/warningList.component.vue"
|
||||||
|
import {getPreviousDay} from "@/utils/utils";
|
||||||
|
import("@/assets/style/pageCommon.component.scss")
|
||||||
|
|
||||||
|
|
||||||
|
Component.registerHooks([
|
||||||
|
'beforeRouteLeave',
|
||||||
|
]);
|
||||||
|
@Component({
|
||||||
|
template,
|
||||||
|
components: {
|
||||||
|
TitleComponent,
|
||||||
|
WarningListComponent
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class RightSideComponent extends Vue {
|
||||||
|
//标题图片
|
||||||
|
imgSrc = require("@/assets/icons/png/env/env-title-icon.png");
|
||||||
|
imgMsgSrc = require("@/assets/icons/png/message-icon.png");
|
||||||
|
imgVideoSrc = require("@/assets/icons/png/video-icon.png");
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
get dataList() {
|
||||||
|
// return this.$store.state.warningList.filter(item => item.model === 'env')
|
||||||
|
return this.$store.state.eventList
|
||||||
|
}
|
||||||
|
//展示告警信息
|
||||||
|
showWaring(item) {
|
||||||
|
|
||||||
|
const levelMap = {
|
||||||
|
1:'一级',
|
||||||
|
2:'二级',
|
||||||
|
3:'三级',
|
||||||
|
4:'四级',
|
||||||
|
}
|
||||||
|
const levelClassMap = {
|
||||||
|
4:'blue',
|
||||||
|
3:'yellow',
|
||||||
|
2:'orange',
|
||||||
|
1:'red',
|
||||||
|
}
|
||||||
|
console.log(item)
|
||||||
|
this.getItem(Object.assign(item, {
|
||||||
|
level: item.level,
|
||||||
|
levelClass: levelClassMap[item.level],
|
||||||
|
levelName: levelMap[item.level],
|
||||||
|
equipment: '北区广场10号监测仪',
|
||||||
|
tableHeader: [
|
||||||
|
{
|
||||||
|
'prop': 'alarmSubject',
|
||||||
|
'label': '告警主体',
|
||||||
|
'width': '90px',
|
||||||
|
}, {
|
||||||
|
'prop': 'COD',
|
||||||
|
'label': 'COD',
|
||||||
|
}, {
|
||||||
|
'prop': 'standard',
|
||||||
|
'label': '标准值',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableData: [{
|
||||||
|
'alarmSubject': '排放量',
|
||||||
|
'COD': '456m<sup>3</sup>',
|
||||||
|
'standard': '466m<sup>3</sup>',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放浓度',
|
||||||
|
'COD': '2.6mg/L',
|
||||||
|
'standard': '2.5mg/L',
|
||||||
|
}, {
|
||||||
|
'alarmSubject': '排放时间',
|
||||||
|
'COD': getPreviousDay(item.time),
|
||||||
|
'standard': '8:00-22:00',
|
||||||
|
}]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
//点击告警信息
|
||||||
|
@Emit('getItem')
|
||||||
|
getItem(item) {
|
||||||
|
// console.log('item', item)
|
||||||
|
}
|
||||||
|
@Emit('changeMore')
|
||||||
|
changeMore(e){
|
||||||
|
|
||||||
|
}
|
||||||
|
@Emit('openPopVideo')
|
||||||
|
openPopVideo(e){
|
||||||
|
|
||||||
|
}
|
||||||
|
beforeDestroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
<template>
|
||||||
|
<!-- :class="!isScroll?'scroll':''"-->
|
||||||
|
<div class="listScroll" :id="id" ref="box">
|
||||||
|
<slot></slot>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {Component, Emit, Prop, Vue, Watch} from 'vue-property-decorator';
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class ScrollBoxComponent extends Vue {
|
||||||
|
//传入的报警信息列表
|
||||||
|
@Prop({default: 999}) value!: any;
|
||||||
|
@Prop({default: 1}) speed!: any;
|
||||||
|
@Prop({default: 'scrollBox'}) id!: any;
|
||||||
|
height = 0
|
||||||
|
isScroll = true
|
||||||
|
|
||||||
|
get ele0() {
|
||||||
|
return (this.$refs.box as any).children[0];
|
||||||
|
}
|
||||||
|
//第二个slot
|
||||||
|
get ele1() {
|
||||||
|
return (this.$refs.box as any).children[1];
|
||||||
|
}
|
||||||
|
//盒子的可视高度
|
||||||
|
get boxHeight() {
|
||||||
|
return (this.$refs.box as any).clientHeight;
|
||||||
|
}
|
||||||
|
//鼠标移入停止滚动 移出继续滚动
|
||||||
|
setEvent() {
|
||||||
|
(this.$refs.box as any).onmouseenter = () => {
|
||||||
|
this.isScroll = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
(this.$refs.box as any).onmouseleave = () => {
|
||||||
|
this.isScroll = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.start(this.height);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
setHeight(){
|
||||||
|
const scrollDom = document.querySelector("#listScroll") as any
|
||||||
|
scrollDom.addEventListener('scroll',(e)=>{
|
||||||
|
console.log(e.target.scrollTop)
|
||||||
|
let height = e.target.scrollTop
|
||||||
|
if (height >= this.ele0.clientHeight) {
|
||||||
|
this.height = 0;
|
||||||
|
}else{
|
||||||
|
this.height = height
|
||||||
|
}
|
||||||
|
this.start(this.height);
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
removeListener(){
|
||||||
|
const scrollDom = document.querySelector("#listScroll") as any
|
||||||
|
scrollDom.removeEventListener('scroll',(e)=>{
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//滚动方法
|
||||||
|
start(height) {
|
||||||
|
this.ele0.style = `transform:translateY(-${height}px);`;
|
||||||
|
this.ele1.style = `height:${this.boxHeight}px;transform:translateY(-${height}px);overflow: hidden;`;
|
||||||
|
// console.log(height,'height')
|
||||||
|
// console.log(this.boxHeight,'boxHeight')
|
||||||
|
if (height >= this.ele0.clientHeight) {
|
||||||
|
this.height = 0;
|
||||||
|
} else {
|
||||||
|
this.height += this.speed;
|
||||||
|
}
|
||||||
|
if (!this.isScroll) return;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
this.start(this.height);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
//在盒子内容高度小于可视高度时不滚动
|
||||||
|
setTimeout(()=>{
|
||||||
|
if (this.boxHeight < this.ele0.clientHeight) {
|
||||||
|
this.start(this.height);
|
||||||
|
this.setEvent();
|
||||||
|
} else {
|
||||||
|
this.isScroll = false;
|
||||||
|
}
|
||||||
|
},1000)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
//滚动条样式
|
||||||
|
@mixin scrollStyle($width) {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: $width !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||||
|
background: rgba(255, 255, 255, 0.68);
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||||
|
-webkit-border-radius: 2px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.listScroll {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.listScroll.scroll{
|
||||||
|
overflow-y: auto;
|
||||||
|
@include scrollStyle(4px);
|
||||||
|
}
|
||||||
|
.hover {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-header class="admin-header d-flex align-items-center is-justify-space-between">
|
||||||
|
<div class="logo-box d-flex align-items-center">
|
||||||
|
<img src="~@/assets/img/logo.png" width="36" height="31" alt="">
|
||||||
|
<span class="logo-text">智慧消防预警系统</span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<el-link @click="gotoView">大屏展示</el-link>
|
||||||
|
<img style="margin-left: 20px" width="28" height="28" src="~@/assets/img/default-icon.png" alt="">
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="200px" class="nav-side">
|
||||||
|
<el-menu
|
||||||
|
router
|
||||||
|
default-active="/tjfx"
|
||||||
|
class="el-menu-vertical-demo"
|
||||||
|
@open="handleOpen"
|
||||||
|
@close="handleClose"
|
||||||
|
background-color="#545c64"
|
||||||
|
text-color="#fff"
|
||||||
|
active-text-color="#FFFFFF">
|
||||||
|
<el-menu-item v-for="item in menuList" :index="item.path">
|
||||||
|
<i class="el-icon-menu"></i>
|
||||||
|
<span slot="title">{{item.label}}</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-main class="main-box">
|
||||||
|
<router-view></router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {Component, Emit, Prop, PropSync, Vue} from 'vue-property-decorator';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class AdminComponent extends Vue {
|
||||||
|
|
||||||
|
menuList = [
|
||||||
|
{label:'报警统计与分析',path:'/tjfx'},
|
||||||
|
{label:'监控设备信息',path:'/jk'},
|
||||||
|
{label:'值班计划',path:'/duty'},
|
||||||
|
{label:'消防车辆管理',path:'/car'},
|
||||||
|
{label:'消防物资管理',path:'/goods'},
|
||||||
|
{label:'消防设备与设施',path:'/eq'},
|
||||||
|
]
|
||||||
|
created() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
handleOpen(key, keyPath) {
|
||||||
|
console.log(key, keyPath);
|
||||||
|
}
|
||||||
|
handleClose(key, keyPath) {
|
||||||
|
console.log(key, keyPath);
|
||||||
|
}
|
||||||
|
gotoView(){
|
||||||
|
this.$router.push('/home')
|
||||||
|
}
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.admin-header{
|
||||||
|
width: 100%;
|
||||||
|
height: 52px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0px -5px 20px -10px rgba(51,73,94,0.3);
|
||||||
|
color: #000000;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
.logo-text{
|
||||||
|
color: #000000;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.nav-side{
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
background-color: rgb(84, 92, 100);
|
||||||
|
}
|
||||||
|
.main-box{
|
||||||
|
padding: 8px;
|
||||||
|
background: #ECEDEE;
|
||||||
|
}
|
||||||
|
::v-deep{
|
||||||
|
.el-menu-item{
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
.el-menu-item.is-active{
|
||||||
|
background: #409EFF !important;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,125 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="admin-card-box search-area d-flex align-items-center is-justify-space-between">
|
||||||
|
<el-form :inline="true" :model="formInline">
|
||||||
|
<el-form-item label="计划名称">
|
||||||
|
<el-input v-model="formInline.cameraName" placeholder="请输入计划名称"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="计划时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formInline.name"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="-"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="计划类型">
|
||||||
|
<el-select v-model="formInline.type">
|
||||||
|
<el-option value="日计划" label="日计划"></el-option>
|
||||||
|
<el-option value="周计划" label="周计划"></el-option>
|
||||||
|
<el-option value="月度计划" label="月度计划"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="d-flex align-items-center" style="margin-bottom: 22px">
|
||||||
|
<el-button type="primary" icon="el-icon-search">查询</el-button>
|
||||||
|
<el-button class="margin-left-20" icon="el-icon-refresh">清空</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="admin-card-box margin-top-16">
|
||||||
|
<div class="d-flex align-items-center flex-end">
|
||||||
|
<el-button type="primary" icon="el-icon-plus">添加</el-button>
|
||||||
|
<el-button type="danger" plain icon="el-icon-delete">批量删除</el-button>
|
||||||
|
<el-button icon="el-icon-edit-outline">批量修改</el-button>
|
||||||
|
<el-button icon="el-icon-upload2">导入</el-button>
|
||||||
|
<el-button icon="el-icon-download">导出</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
class="margin-top-20"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column
|
||||||
|
type="index"
|
||||||
|
label="序号"
|
||||||
|
width="60"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
label="计划名称"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="startTime"
|
||||||
|
label="开始时间"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="endTime"
|
||||||
|
label="结束时间">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="type"
|
||||||
|
label="计划类型">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="area"
|
||||||
|
label="人员范围">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="position"
|
||||||
|
label="值守地点">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="leader"
|
||||||
|
label="带班领导">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
fixed="right"
|
||||||
|
label="操作"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="small">查看</el-button>
|
||||||
|
<el-button type="text" size="small">编辑</el-button>
|
||||||
|
<el-button type="text" size="small">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="margin-top-16" style="text-align: center">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
layout="total, prev, pager, next"
|
||||||
|
:total="9">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {Component, Emit, Prop, PropSync, Vue} from 'vue-property-decorator';
|
||||||
|
import {dutyDataList} from '../morkData'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class DutyComponent extends Vue {
|
||||||
|
formInline:any = {}
|
||||||
|
tableData = dutyDataList
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search-area{
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,128 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="admin-card-box search-area d-flex align-items-center is-justify-space-between">
|
||||||
|
<el-form :inline="true" :model="formInline">
|
||||||
|
<el-form-item label="摄像头名称">
|
||||||
|
<el-input v-model="formInline.cameraName" placeholder="请输入摄像头名称"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="摄像头编码">
|
||||||
|
<el-input v-model="formInline.cameraCode" placeholder="请输入摄像头编码"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="企业名称">
|
||||||
|
<el-input v-model="formInline.companyName" placeholder="请输入企业名称"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="摄像头类型">
|
||||||
|
<el-select v-model="formInline.cameraType">
|
||||||
|
<el-option value="简型摄像头" label="简型摄像头"></el-option>
|
||||||
|
<el-option value="枪机" label="枪机"></el-option>
|
||||||
|
<el-option value="云台" label="云台"></el-option>
|
||||||
|
<el-option value="球机" label="球机"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="d-flex align-items-center" style="margin-bottom: 22px">
|
||||||
|
<el-button type="primary" icon="el-icon-search">查询</el-button>
|
||||||
|
<el-button class="margin-left-20" icon="el-icon-refresh">清空</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="admin-card-box margin-top-16">
|
||||||
|
<div class="d-flex align-items-center flex-end">
|
||||||
|
<el-button type="primary" icon="el-icon-plus">添加</el-button>
|
||||||
|
<el-button type="danger" plain icon="el-icon-delete">批量删除</el-button>
|
||||||
|
<el-button icon="el-icon-edit-outline">批量修改</el-button>
|
||||||
|
<el-button icon="el-icon-upload2">导入</el-button>
|
||||||
|
<el-button icon="el-icon-download">导出</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
class="margin-top-20"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column
|
||||||
|
type="index"
|
||||||
|
label="序号"
|
||||||
|
width="60"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="cameraName"
|
||||||
|
label="摄像头名称"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="companyName"
|
||||||
|
label="企业名称"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="cameraCode"
|
||||||
|
label="摄像头编码">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="position"
|
||||||
|
label="安装位置">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="monitorObject"
|
||||||
|
label="监控对象">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="cameraType"
|
||||||
|
label="摄像头类型">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="status"
|
||||||
|
label="状态">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span :class="scope.row.status?'green-text':'red-text'">
|
||||||
|
{{scope.row.status?'在线':'离线'}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
fixed="right"
|
||||||
|
label="操作"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="small">查看</el-button>
|
||||||
|
<el-button type="text" size="small">编辑</el-button>
|
||||||
|
<el-button type="text" size="small">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="margin-top-16" style="text-align: center">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
layout="total, prev, pager, next"
|
||||||
|
:total="8">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {Component, Emit, Prop, PropSync, Vue} from 'vue-property-decorator';
|
||||||
|
import {jkDataList} from '../morkData'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class JkComponent extends Vue {
|
||||||
|
formInline:any = {}
|
||||||
|
tableData = jkDataList
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search-area{
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,160 @@
|
||||||
|
<template>
|
||||||
|
<div class="d-flex flex-direction-column">
|
||||||
|
<div class="d-flex flex-0 height-auto">
|
||||||
|
<div class="admin-card-box flex-1">
|
||||||
|
<div class="title d-flex align-items-center">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img width="20" height="20" src="~@/assets/icons/png/admin-title-icon.png" alt="">
|
||||||
|
<span class="admin-title-text">报警类型分析</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="margin-top-16">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="boxTime1"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="-"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
<hbt-echarts className="charts-box" :options="pieOpt" @onChartInit="getEcharts($event,'pie')"></hbt-echarts>
|
||||||
|
</div>
|
||||||
|
<div class="admin-card-box flex-1" style="margin-left: 8px;margin-right: 8px">
|
||||||
|
<div class="title d-flex align-items-center is-justify-space-between">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img width="20" height="20" src="~@/assets/icons/png/admin-title-icon.png" alt="">
|
||||||
|
<span class="admin-title-text">处置分析</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-select v-model="fxVal">
|
||||||
|
<el-option label="烟雾分析" value="烟雾分析"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hbt-echarts class="margin-top-16" className="charts-box" :options="lineOpt" @onChartInit="getEcharts($event,'line')"></hbt-echarts>
|
||||||
|
</div>
|
||||||
|
<div class="admin-card-box flex-1">
|
||||||
|
<div class="title d-flex align-items-center is-justify-space-between">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img width="20" height="20" src="~@/assets/icons/png/admin-title-icon.png" alt="">
|
||||||
|
<span class="admin-title-text">环比对比分析</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-select v-model="hbVal">
|
||||||
|
<el-option label="月" value="月"></el-option>
|
||||||
|
<el-option label="周" value="周"></el-option>
|
||||||
|
<el-option label="日" value="日"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hbt-echarts class="margin-top-16" className="charts-box" :options="barOpt" @onChartInit="getEcharts($event,'bar')"></hbt-echarts>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="admin-card-box d-flex flex-direction-column margin-top-16 flex-1" style="min-height: calc(100vh - 530px)">
|
||||||
|
<div class="title d-flex align-items-center is-justify-space-between">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img width="20" height="20" src="~@/assets/icons/png/admin-title-icon.png" alt="">
|
||||||
|
<span class="admin-title-text">报警历史趋势分析</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hbt-echarts class="margin-top-16 flex-1" style="min-height: calc(100vh - 630px)" className="charts-box" :options="linesOpt" @onChartInit="getEcharts($event,'lines')"></hbt-echarts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {Component, Emit, Prop, PropSync, Vue} from 'vue-property-decorator';
|
||||||
|
import {pieData,lineData,barData,linesData} from './chartData.js'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class TjfxComponent extends Vue {
|
||||||
|
|
||||||
|
|
||||||
|
//环图实例
|
||||||
|
pie:any = {}
|
||||||
|
line:any = {}
|
||||||
|
boxTime1:any = ''
|
||||||
|
fxVal:any = '烟雾分析'
|
||||||
|
hbVal:any = '月'
|
||||||
|
created() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
handleOpen(key, keyPath) {
|
||||||
|
console.log(key, keyPath);
|
||||||
|
}
|
||||||
|
handleClose(key, keyPath) {
|
||||||
|
console.log(key, keyPath);
|
||||||
|
}
|
||||||
|
pieOpt = {}
|
||||||
|
lineOpt = {}
|
||||||
|
barOpt = {}
|
||||||
|
linesOpt = {}
|
||||||
|
getEcharts(e,type){
|
||||||
|
this[type] = e
|
||||||
|
switch (type) {
|
||||||
|
case 'pie':
|
||||||
|
this.pieOpt = pieData;
|
||||||
|
break;
|
||||||
|
case 'line':
|
||||||
|
this.lineOpt = lineData;
|
||||||
|
break;
|
||||||
|
case 'bar':
|
||||||
|
this.barOpt = barData;
|
||||||
|
break;
|
||||||
|
case 'lines':
|
||||||
|
this.linesOpt = linesData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.admin-header{
|
||||||
|
width: 100%;
|
||||||
|
height: 52px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0px -5px 20px -10px rgba(51,73,94,0.3);
|
||||||
|
color: #000000;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
.logo-text{
|
||||||
|
color: #000000;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.nav-side{
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
background-color: rgb(84, 92, 100);
|
||||||
|
}
|
||||||
|
.main-box{
|
||||||
|
padding: 8px;
|
||||||
|
background: #ECEDEE;
|
||||||
|
}
|
||||||
|
.charts-box{
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
::v-deep{
|
||||||
|
.el-menu-item{
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
.el-menu-item.is-active{
|
||||||
|
background: #409EFF !important;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,691 @@
|
||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<h2>分片上传示例</h2>
|
||||||
|
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
class="upload-demo"
|
||||||
|
action="http://127.0.0.1:8088/file/upload"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:file-list="uploadFileList"
|
||||||
|
:show-file-list="false"
|
||||||
|
:auto-upload="false"
|
||||||
|
multiple
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<el-button type="primary" plain>选择文件</el-button>
|
||||||
|
</template>
|
||||||
|
<el-button style="margin-left: 10px;" type="success" plain @click="handler">上传</el-button>
|
||||||
|
<el-button type="danger" plain @click="clearFileHandler">清空</el-button>
|
||||||
|
</el-upload>
|
||||||
|
<!-- 文件列表 -->
|
||||||
|
<div class="file-list-wrapper">
|
||||||
|
<el-collapse>
|
||||||
|
<el-collapse-item v-for="(item, index) in uploadFileList" :key="index">
|
||||||
|
<template #title>
|
||||||
|
<div class="upload-file-item">
|
||||||
|
<div class="file-info-item file-name" :title="item.name">{{ item.name }}</div>
|
||||||
|
<div class="file-info-item file-size">{{ transformByte(item.size) }}</div>
|
||||||
|
<div class="file-info-item file-progress">
|
||||||
|
<span class="file-progress-label"/>
|
||||||
|
<el-progress :percentage="item.uploadProgress" class="file-progress-value"/>
|
||||||
|
</div>
|
||||||
|
<div class="file-info-item file-size"><span/>
|
||||||
|
<el-tag v-if="item.status === '等待上传'" size="small" type="info">等待上传</el-tag>
|
||||||
|
<el-tag v-else-if="item.status === '校验md5'" size="small" type="warning">校验MD5</el-tag>
|
||||||
|
<el-tag v-else-if="item.status === '正在上传'" size="small">正在上传</el-tag>
|
||||||
|
<el-tag v-else-if="item.status === '上传成功'" size="small" type="success">上传完成</el-tag>
|
||||||
|
<el-tag v-else size="small" type="danger">上传错误</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="file-chunk-list-wrapper">
|
||||||
|
<!-- 分片列表 -->
|
||||||
|
<el-table :data="item.chunkList" max-height="400" style="width: 100%">
|
||||||
|
<el-table-column prop="chunkNumber" label="分片序号" width="180"/>
|
||||||
|
<el-table-column prop="progress" label="上传进度">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-progress
|
||||||
|
v-if="!row.status || row.progressStatus === 'normal'"
|
||||||
|
:percentage="row.progress"
|
||||||
|
/>
|
||||||
|
<el-progress
|
||||||
|
v-else
|
||||||
|
:percentage="row.progress"
|
||||||
|
:status="row.progressStatus"
|
||||||
|
:text-inside="true"
|
||||||
|
:stroke-width="16"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" label="状态" width="180"/>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SparkMD5 from 'spark-md5'
|
||||||
|
import { check, init, merge, getId } from '@/api/upload'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'MultipartUpload',
|
||||||
|
setup() {
|
||||||
|
// file_upload_id
|
||||||
|
const FILE_UPLOAD_ID_KEY = 'file_upload_id'
|
||||||
|
|
||||||
|
// 分片大小
|
||||||
|
const chunkSize = 5 * 1024 * 1024
|
||||||
|
|
||||||
|
// 当前文件下标索引
|
||||||
|
let currentFileIndex = 0
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
const FileStatus = {
|
||||||
|
wait: '等待上传',
|
||||||
|
getMd5: '校验md5',
|
||||||
|
chip: '正在创建序列',
|
||||||
|
uploading: '正在上传',
|
||||||
|
success: '上传成功',
|
||||||
|
error: '上传错误'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传并发数
|
||||||
|
const simultaneousUploads = ref(3)
|
||||||
|
const uploadIdInfo = ref(null)
|
||||||
|
const uploadFileList = ref([])
|
||||||
|
const imgDataUrl = ref('')
|
||||||
|
|
||||||
|
const transformByte = (size) => {
|
||||||
|
if (!size) {
|
||||||
|
return '0B'
|
||||||
|
}
|
||||||
|
const unitSize = 1024
|
||||||
|
if (size < unitSize) {
|
||||||
|
return size + ' B'
|
||||||
|
}
|
||||||
|
// KB
|
||||||
|
if (size < Math.pow(unitSize, 2)) {
|
||||||
|
return (size / unitSize).toFixed(2) + ' K'
|
||||||
|
}
|
||||||
|
// MB
|
||||||
|
if (size < Math.pow(unitSize, 3)) {
|
||||||
|
return (size / Math.pow(unitSize, 2)).toFixed(2) + ' MB'
|
||||||
|
}
|
||||||
|
// GB
|
||||||
|
if (size < Math.pow(unitSize, 4)) {
|
||||||
|
return (size / Math.pow(unitSize, 3)).toFixed(2) + ' GB'
|
||||||
|
}
|
||||||
|
// TB
|
||||||
|
return (size / Math.pow(unitSize, 4)).toFixed(2) + ' TB'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始上传文件
|
||||||
|
*/
|
||||||
|
const handler = () => {
|
||||||
|
// 判断文件列表是否为空
|
||||||
|
if (uploadFileList.value.length === 0) {
|
||||||
|
ElMessage.error('请先选择文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 当前操作文件
|
||||||
|
const currentFile = uploadFileList.value[currentFileIndex]
|
||||||
|
|
||||||
|
// 更新上传标签
|
||||||
|
if (currentFile) {
|
||||||
|
currentFile.status = FileStatus.getMd5
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截取封面图片
|
||||||
|
// ScreenshotVideo(currentFile.raw);
|
||||||
|
|
||||||
|
// 计算文件MD5
|
||||||
|
if (!currentFile) return
|
||||||
|
getFileMd5(currentFile.raw, async(md5, totalChunks) => {
|
||||||
|
// 上传约定upLoadId
|
||||||
|
const uploadResult = await getupLoadId({})
|
||||||
|
// 创建分片
|
||||||
|
currentFile.status = FileStatus.chip
|
||||||
|
|
||||||
|
// 创建分片
|
||||||
|
const fileChunks = createFileChunk(currentFile.raw, chunkSize)
|
||||||
|
|
||||||
|
// 重命名文件
|
||||||
|
const fileName = currentFile.name
|
||||||
|
|
||||||
|
// 获取文件类型
|
||||||
|
const type = currentFile.name.substring(currentFile.name.lastIndexOf('.') + 1)
|
||||||
|
// let type = fileSuffixTypeUtil(currentFile.name)
|
||||||
|
|
||||||
|
const param = {
|
||||||
|
id: uploadResult.data,
|
||||||
|
originalName: fileName,
|
||||||
|
applicationName: fileName,
|
||||||
|
fileSize: currentFile.size,
|
||||||
|
chunkSize: chunkSize,
|
||||||
|
size: chunkSize,
|
||||||
|
partCount: totalChunks,
|
||||||
|
contentType: 'application/octet-stream',
|
||||||
|
fileType: type
|
||||||
|
}
|
||||||
|
// 获取上传url
|
||||||
|
uploadIdInfo.value = await getFileUploadUrls(param)
|
||||||
|
saveFileUploadId(uploadIdInfo.value.data.uploadId)
|
||||||
|
|
||||||
|
const uploadUrls = uploadIdInfo.value.data.urlList
|
||||||
|
currentFile.chunkList = []
|
||||||
|
// $set(currentFile, 'chunkList', [])
|
||||||
|
|
||||||
|
if (uploadUrls !== undefined) {
|
||||||
|
if (fileChunks.length !== uploadUrls.length) {
|
||||||
|
ElMessage.error('文件分片上传地址获取错误')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileChunks.map((chunkItem, index) => {
|
||||||
|
currentFile.chunkList.push({
|
||||||
|
chunkNumber: index + 1,
|
||||||
|
chunk: chunkItem,
|
||||||
|
uploadUrl: uploadUrls[index],
|
||||||
|
progress: 0,
|
||||||
|
status: '—'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
let tempFileChunks = []
|
||||||
|
|
||||||
|
currentFile.chunkList.forEach((item) => {
|
||||||
|
tempFileChunks.push(item)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新状态
|
||||||
|
currentFile.status = FileStatus.uploading
|
||||||
|
|
||||||
|
// 上传
|
||||||
|
await uploadChunkBase(tempFileChunks)
|
||||||
|
|
||||||
|
// 处理分片列表,删除已上传的分片
|
||||||
|
tempFileChunks = processUploadChunkList(tempFileChunks)
|
||||||
|
|
||||||
|
// 判断是否单文件上传或者分片上传
|
||||||
|
if (uploadIdInfo.value.uploadId === 'SingleFileUpload') {
|
||||||
|
// 更新状态
|
||||||
|
currentFile.status = FileStatus.success
|
||||||
|
} else {
|
||||||
|
getVideoTime(currentFile.raw, async(duration) => {
|
||||||
|
// 合并文件
|
||||||
|
const mergeResult = await mergeFile({
|
||||||
|
uploadId: uploadIdInfo.value.data.uploadId,
|
||||||
|
extractName: uploadIdInfo.value.data.extractName,
|
||||||
|
originalName: fileName,
|
||||||
|
name: fileName,
|
||||||
|
id: uploadResult.data,
|
||||||
|
type: type,
|
||||||
|
duration
|
||||||
|
})
|
||||||
|
|
||||||
|
// 合并文件状态
|
||||||
|
if (!mergeResult) {
|
||||||
|
currentFile.status = FileStatus.error
|
||||||
|
ElMessage.error(mergeResult.error)
|
||||||
|
} else {
|
||||||
|
currentFile.status = FileStatus.success
|
||||||
|
console.log('文件访问地址:' + mergeResult)
|
||||||
|
ElMessage.success(`上传成功,文件地址:${mergeResult}`)
|
||||||
|
// 文件下标偏移
|
||||||
|
currentFileIndex++
|
||||||
|
// 递归上传下一个文件
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// TODO 持久化保存上传文件信息
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取视频时长
|
||||||
|
const getVideoTime = (file, fn) => {
|
||||||
|
const url = URL.createObjectURL(file)
|
||||||
|
const video = document.createElement('video')
|
||||||
|
|
||||||
|
video.src = url
|
||||||
|
video.addEventListener('loadedmetadata', function() {
|
||||||
|
console.log('视频长度(秒): ', this.duration)
|
||||||
|
fn(secToHHMMSS(this.duration))
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
video.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const secToHHMMSS = (time) => {
|
||||||
|
let hours = Math.floor(time / 3600)
|
||||||
|
let minutes = Math.floor((time - (hours * 3600)) / 60)
|
||||||
|
let seconds = Math.floor(time - (hours * 3600) - (minutes * 60))
|
||||||
|
hours = (hours < 10) ? '0' + hours : hours
|
||||||
|
minutes = (minutes < 10) ? '0' + minutes : minutes
|
||||||
|
seconds = (seconds < 10) ? '0' + seconds : seconds
|
||||||
|
return hours + ':' + minutes + ':' + seconds
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 清空列表
|
||||||
|
*/
|
||||||
|
const clearFileHandler = () => {
|
||||||
|
uploadFileList.value = []
|
||||||
|
uploadIdInfo.value = null
|
||||||
|
currentFileIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件列表
|
||||||
|
* @param {*} file
|
||||||
|
* @param {*} fileList
|
||||||
|
*/
|
||||||
|
const handleFileChange = (file, fileList) => {
|
||||||
|
// if (!beforeUploadVideo(file)) return
|
||||||
|
|
||||||
|
uploadFileList.value = fileList
|
||||||
|
|
||||||
|
uploadFileList.value.forEach((item) => {
|
||||||
|
// 初始化自定义属性
|
||||||
|
initFileProperties(item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化文件属性
|
||||||
|
* @param file
|
||||||
|
*/
|
||||||
|
const initFileProperties = (file) => {
|
||||||
|
file.chunkList = []
|
||||||
|
file.status = FileStatus.wait
|
||||||
|
file.progressStatus = 'warning'
|
||||||
|
file.uploadProgress = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除文件列表
|
||||||
|
* @param {*} file
|
||||||
|
* @param {*} fileList
|
||||||
|
*/
|
||||||
|
const handleRemove = (file, fileList) => {
|
||||||
|
uploadFileList.value = fileList
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查上传文件格式
|
||||||
|
* @param {*} file
|
||||||
|
*/
|
||||||
|
const beforeUploadVideo = (file) => {
|
||||||
|
const type = file.name.substring(file.name.lastIndexOf('.') + 1)
|
||||||
|
if (['mp4', 'ogg', 'flv', 'avi', 'wmv', 'rmvb'].indexOf(type) === -1) {
|
||||||
|
ElMessage.error('请上传正确的视频格式')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件新名称
|
||||||
|
* @param file
|
||||||
|
* @param md5
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
const getNewFileName = (file, md5) => {
|
||||||
|
return new Date().getTime() + file.name
|
||||||
|
// return md5 + '-' + file.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分片读取文件 MD5
|
||||||
|
*/
|
||||||
|
const getFileMd5 = (file, callback) => {
|
||||||
|
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
|
||||||
|
const fileReader = new FileReader()
|
||||||
|
// 计算分片数
|
||||||
|
const totalChunks = Math.ceil(file.size / chunkSize)
|
||||||
|
console.log('总分片数:' + totalChunks)
|
||||||
|
let currentChunk = 0
|
||||||
|
const spark = new SparkMD5.ArrayBuffer()
|
||||||
|
loadNext()
|
||||||
|
fileReader.onload = function(e) {
|
||||||
|
try {
|
||||||
|
spark.append(e.target.result)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('获取Md5错误:' + currentChunk)
|
||||||
|
}
|
||||||
|
if (currentChunk < totalChunks) {
|
||||||
|
currentChunk++
|
||||||
|
loadNext()
|
||||||
|
} else {
|
||||||
|
callback(spark.end(), totalChunks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileReader.onerror = function() {
|
||||||
|
console.warn('读取Md5失败,文件读取错误')
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadNext() {
|
||||||
|
const start = currentChunk * chunkSize
|
||||||
|
const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
|
||||||
|
// 注意这里的 fileRaw
|
||||||
|
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件分片
|
||||||
|
* @param file
|
||||||
|
* @param size
|
||||||
|
* @returns {*[]}
|
||||||
|
*/
|
||||||
|
const createFileChunk = (file, size = chunkSize) => {
|
||||||
|
const fileChunkList = []
|
||||||
|
let count = 0
|
||||||
|
while (count < file.size) {
|
||||||
|
fileChunkList.push({
|
||||||
|
file: file.slice(count, count + size)
|
||||||
|
})
|
||||||
|
count += size
|
||||||
|
}
|
||||||
|
return fileChunkList
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理即将上传的分片列表,判断是否有已上传的分片,有则从列表中删除
|
||||||
|
* @param chunkList
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
const processUploadChunkList = (chunkList) => {
|
||||||
|
const currentFile = uploadFileList.value[currentFileIndex]
|
||||||
|
const chunkUploadedList = currentFile.chunkUploadedList
|
||||||
|
if (chunkUploadedList === undefined || chunkUploadedList === null || chunkUploadedList.length === 0) {
|
||||||
|
return chunkList
|
||||||
|
}
|
||||||
|
for (let i = chunkList.length - 1; i >= 0; i--) {
|
||||||
|
const chunkItem = chunkList[currentFileIndex]
|
||||||
|
for (let j = 0; j < chunkUploadedList.length; j++) {
|
||||||
|
if (chunkItem.chunkNumber === chunkUploadedList[j]) {
|
||||||
|
chunkList.splice(i, 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunkList
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传分片文件
|
||||||
|
* @param chunkList
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
const uploadChunkBase = (chunkList) => {
|
||||||
|
let successCount = 0
|
||||||
|
const totalChunks = chunkList.length
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const handler = () => {
|
||||||
|
if (chunkList.length) {
|
||||||
|
const chunkItem = chunkList.shift()
|
||||||
|
chunkItem.uploadUrl = chunkItem.uploadUrl.replace('http://146.56.192.100:10000', 'https://minio.hanbangtang.com')
|
||||||
|
// 直接上传二进制,不需要构造 FormData,否则上传后文件损坏
|
||||||
|
axios.put(chunkItem.uploadUrl, chunkItem.chunk.file, {
|
||||||
|
// 上传进度处理
|
||||||
|
onUploadProgress: checkChunkUploadProgress(chunkItem),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/octet-stream'
|
||||||
|
}
|
||||||
|
}).then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
console.log('分片:' + chunkItem.chunkNumber + ' 上传成功')
|
||||||
|
// 如果长度为1,说明是单文件,直接退出
|
||||||
|
// if (chunkList.length === 1) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
successCount++
|
||||||
|
// 继续上传下一个分片
|
||||||
|
handler()
|
||||||
|
} else {
|
||||||
|
console.log('上传失败:' + response.status + ',' + response.statusText)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
// 更新状态
|
||||||
|
console.log('分片:' + chunkItem.chunkNumber + ' 上传失败,' + error)
|
||||||
|
// 重新添加到队列中
|
||||||
|
chunkList.push(chunkItem)
|
||||||
|
handler()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (successCount >= totalChunks) {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 并发
|
||||||
|
for (let i = 0; i < simultaneousUploads.value; i++) {
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件上传地址
|
||||||
|
* @param fileParam
|
||||||
|
* @returns {Promise<axios.AxiosResponse<any>>}
|
||||||
|
*/
|
||||||
|
const getFileUploadUrls = (fileParam) => {
|
||||||
|
return init(fileParam)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文件上传id
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
const saveFileUploadId = (data) => {
|
||||||
|
localStorage.setItem(FILE_UPLOAD_ID_KEY, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传校验
|
||||||
|
* @param md5
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
const checkFileUploadedByMd5 = (md5) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
check(md5).then(response => {
|
||||||
|
console.log(response)
|
||||||
|
resolve(response)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 上传校验
|
||||||
|
* @param md5
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
const getupLoadId = (data) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getId({}).then(response => {
|
||||||
|
console.log(response)
|
||||||
|
resolve(response)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并分片数据
|
||||||
|
* @param fileParam
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
const mergeFile = (fileParam) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('id', fileParam.id)
|
||||||
|
formData.append('extractName', fileParam.extractName)
|
||||||
|
formData.append('uploadId', fileParam.uploadId)
|
||||||
|
formData.append('duration', fileParam.duration)
|
||||||
|
merge(formData).then(response => {
|
||||||
|
console.log(response)
|
||||||
|
const data = response
|
||||||
|
if (!data) {
|
||||||
|
// data.msg = FileStatus.error
|
||||||
|
resolve(data)
|
||||||
|
} else {
|
||||||
|
// data.msg = FileStatus.success
|
||||||
|
resolve(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// .catch(error => {
|
||||||
|
// $message.error('合并文件失败:' + error)
|
||||||
|
// file.status = FileStatus.error
|
||||||
|
// reject()
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查分片上传进度
|
||||||
|
* @param item
|
||||||
|
* @returns {(function(*): void)|*}
|
||||||
|
*/
|
||||||
|
const checkChunkUploadProgress = (item) => {
|
||||||
|
return p => {
|
||||||
|
item.progress = parseInt(String((p.loaded / p.total) * 100))
|
||||||
|
updateChunkUploadStatus(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新上传状态
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
const updateChunkUploadStatus = (item) => {
|
||||||
|
let status = FileStatus.uploading
|
||||||
|
let progressStatus = 'normal'
|
||||||
|
if (item.progress >= 100) {
|
||||||
|
status = FileStatus.success
|
||||||
|
progressStatus = 'success'
|
||||||
|
}
|
||||||
|
const chunkIndex = item.chunkNumber - 1
|
||||||
|
const currentChunk = uploadFileList.value[currentFileIndex].chunkList[chunkIndex]
|
||||||
|
// 修改状态
|
||||||
|
currentChunk.status = status
|
||||||
|
currentChunk.progressStatus = progressStatus
|
||||||
|
// 更新状态
|
||||||
|
// $set(uploadFileList[currentFileIndex].chunkList, chunkIndex, currentChunk)
|
||||||
|
uploadFileList.value[currentFileIndex].chunkList.splice(chunkIndex, 1, currentChunk)
|
||||||
|
// 获取文件上传进度
|
||||||
|
getCurrentFileProgress()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件上传进度
|
||||||
|
*/
|
||||||
|
const getCurrentFileProgress = () => {
|
||||||
|
const currentFile = uploadFileList.value[currentFileIndex]
|
||||||
|
if (!currentFile || !currentFile.chunkList) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const chunkList = currentFile.chunkList
|
||||||
|
const uploadedSize = chunkList.map((item) => item.chunk.file.size * item.progress).reduce((acc, cur) => acc + cur)
|
||||||
|
// 计算方式:已上传大小 / 文件总大小
|
||||||
|
currentFile.uploadProgress = parseInt((uploadedSize / currentFile.size).toFixed(2))
|
||||||
|
// $set(uploadFileList.value, currentFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
uploadIdInfo,
|
||||||
|
uploadFileList,
|
||||||
|
imgDataUrl,
|
||||||
|
transformByte,
|
||||||
|
handler,
|
||||||
|
clearFileHandler,
|
||||||
|
handleFileChange,
|
||||||
|
initFileProperties,
|
||||||
|
handleRemove,
|
||||||
|
beforeUploadVideo,
|
||||||
|
getNewFileName,
|
||||||
|
getFileMd5,
|
||||||
|
createFileChunk,
|
||||||
|
processUploadChunkList,
|
||||||
|
uploadChunkBase,
|
||||||
|
getFileUploadUrls,
|
||||||
|
saveFileUploadId,
|
||||||
|
checkFileUploadedByMd5,
|
||||||
|
mergeFile,
|
||||||
|
checkChunkUploadProgress,
|
||||||
|
updateChunkUploadStatus,
|
||||||
|
getCurrentFileProgress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-wrapper {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info-item {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-file-item {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-progress {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-progress-value {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
width: 190px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-size {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploader-example {
|
||||||
|
width: 880px;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 40px auto 0;
|
||||||
|
font-size: 12px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploader-example .uploader-btn {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploader-example .uploader-list {
|
||||||
|
max-height: 440px;
|
||||||
|
overflow: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|