update code
parent
e7a9027c5d
commit
542310a7d8
|
@ -10,6 +10,9 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
|
"@easydarwin/easywasmplayer": "^4.0.10",
|
||||||
|
"emittery": "^0.8.1",
|
||||||
|
"logt": "^1.4.1",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.9",
|
||||||
"element-ui": "^2.15.13",
|
"element-ui": "^2.15.13",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
|
@ -17,7 +20,6 @@
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.1.3",
|
"less-loader": "^11.1.3",
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-h265-player": "^0.0.24",
|
|
||||||
"vue-router": "^4.2.2"
|
"vue-router": "^4.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -3292,3 +3292,7 @@ table{
|
||||||
background-color: rgb(1, 169, 255);
|
background-color: rgb(1, 169, 255);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
.bg-date-picker-pop{
|
||||||
|
background-image: url('../images/list_bgd.png');
|
||||||
|
border:solid 1px rgb(1, 169, 255);
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615876998076" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="940" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M791.893333 0H232.106667C105.813333 0 0 105.813333 0 232.106667v559.786666C0 918.186667 105.813333 1024 232.106667 1024h559.786666c129.706667 0 232.106667-105.813333 232.106667-232.106667V232.106667C1024 105.813333 918.186667 0 791.893333 0z m-116.053333 508.586667l-273.066667 170.666666c-3.413333 3.413333-6.826667 3.413333-10.24 3.413334-3.413333 0-6.826667 0-6.826666-3.413334-6.826667-3.413333-10.24-10.24-10.24-13.653333v-307.2c0-6.826667 3.413333-10.24 6.826666-13.653333 3.413333-3.413333 10.24-3.413333 17.066667 0l273.066667 136.533333c6.826667 3.413333 10.24 6.826667 10.24 13.653333s-3.413333 10.24-6.826667 13.653334z" fill="#DFDFDF" p-id="941"></path></svg>
|
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,7 @@
|
||||||
|
import H265PlayerComponent from './index.vue'
|
||||||
|
export { H265Player, H265PlayerConstants } from './utils/player'
|
||||||
|
|
||||||
|
H265PlayerComponent.install = Vue =>
|
||||||
|
Vue.component('H265Player', H265PlayerComponent)
|
||||||
|
|
||||||
|
export default H265PlayerComponent
|
|
@ -0,0 +1,154 @@
|
||||||
|
<template>
|
||||||
|
<div class="h265-player-container">
|
||||||
|
<img
|
||||||
|
v-show="isShowPlayIcon"
|
||||||
|
class="play-icon"
|
||||||
|
:src="PlayButton"
|
||||||
|
alt="PlayButton"
|
||||||
|
/>
|
||||||
|
<div class="player" :id="elemId"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import PlayButton from './assets/play-button.svg'
|
||||||
|
import {
|
||||||
|
getRandomElemId,
|
||||||
|
H265PlayerConstants,
|
||||||
|
H265Player
|
||||||
|
} from './utils/player.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
url: {
|
||||||
|
validator: prop =>
|
||||||
|
[null, undefined].includes(prop) || typeof prop === 'string',
|
||||||
|
default: null,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
maxRetryCount: {
|
||||||
|
validator: prop => typeof prop === 'number' && prop >= 1,
|
||||||
|
default: 3,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
PlayButton,
|
||||||
|
elemId: '',
|
||||||
|
isShowPlayIcon: false
|
||||||
|
}),
|
||||||
|
watch: {
|
||||||
|
url: {
|
||||||
|
async handler (newUrl) {
|
||||||
|
if (!newUrl) return
|
||||||
|
await this.$nextTick()
|
||||||
|
const action = this.player ? this.hotBoot : this.coolBoot
|
||||||
|
action(newUrl)
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
hotBoot (url) {
|
||||||
|
if (!this.player) {
|
||||||
|
this.coolBoot(url)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.player.changeUrl(url)
|
||||||
|
},
|
||||||
|
coolBoot (url) {
|
||||||
|
const player = new H265Player(this.elemId, this.maxRetryCount)
|
||||||
|
|
||||||
|
player.play(url)
|
||||||
|
|
||||||
|
player.on(H265PlayerConstants.on_error, e => {
|
||||||
|
this.$emit('on-error', e)
|
||||||
|
})
|
||||||
|
|
||||||
|
player.on(H265PlayerConstants.on_play, e => {
|
||||||
|
this.$emit('on-play', e)
|
||||||
|
this.isShowPlayIcon = false
|
||||||
|
})
|
||||||
|
|
||||||
|
player.on(H265PlayerConstants.on_dispose, e => {
|
||||||
|
this.$emit('on-dispose', e)
|
||||||
|
this.isShowPlayIcon = true
|
||||||
|
})
|
||||||
|
|
||||||
|
this.player = player
|
||||||
|
},
|
||||||
|
getPlayer () {
|
||||||
|
return this.player
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.elemId = getRandomElemId()
|
||||||
|
this.player = null
|
||||||
|
|
||||||
|
this.$once('hook:beforeDestroy', () => {
|
||||||
|
if (this.player) {
|
||||||
|
this.player.dispose()
|
||||||
|
this.player = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.$once('hook:deactivated', () => {
|
||||||
|
if (this.player) {
|
||||||
|
this.player.dispose()
|
||||||
|
this.player = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.h265-player-container,
|
||||||
|
.player {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h265-player-container {
|
||||||
|
position: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
object-fit: contain;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player {
|
||||||
|
background-color: #343231;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep {
|
||||||
|
.iconqingxiLOGO,
|
||||||
|
span.fa-volume-off,
|
||||||
|
span.fa-stop {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas + div {
|
||||||
|
background-color: rgba(0,0,0,0.05) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.fa-volume-off + .no-padding {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.fa-pause,
|
||||||
|
span.fa-expand {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Binary file not shown.
|
@ -0,0 +1,20 @@
|
||||||
|
import LogT from 'logt';
|
||||||
|
const TAG = 'h265-player';
|
||||||
|
const log = new LogT(5);
|
||||||
|
export const logger = {
|
||||||
|
ok: (...args) => {
|
||||||
|
log.silly(TAG, '', ...args);
|
||||||
|
},
|
||||||
|
info: (...args) => {
|
||||||
|
log.info(TAG, '', ...args);
|
||||||
|
},
|
||||||
|
warn: (...args) => {
|
||||||
|
log.warn(TAG, '', ...args);
|
||||||
|
},
|
||||||
|
fatal: (...args) => {
|
||||||
|
log.error(TAG, '', ...args);
|
||||||
|
},
|
||||||
|
verbose: (...args) => {
|
||||||
|
log.verbose(TAG, '', ...args);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,204 @@
|
||||||
|
import WasmPlayer from '@easydarwin/easywasmplayer/EasyWasmPlayer.js';
|
||||||
|
import Emittery from 'emittery';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { logger } from './logger';
|
||||||
|
/**
|
||||||
|
* 获取一个随机的 元素id,用作播放器的元素id
|
||||||
|
*/
|
||||||
|
export const getRandomElemId = () => {
|
||||||
|
return uuidv4();
|
||||||
|
};
|
||||||
|
export var H265PlayerConstants;
|
||||||
|
(function (H265PlayerConstants) {
|
||||||
|
H265PlayerConstants["on_play"] = "on_play";
|
||||||
|
H265PlayerConstants["on_stop"] = "on_stop";
|
||||||
|
H265PlayerConstants["on_endLoading"] = "on_endLoading";
|
||||||
|
H265PlayerConstants["on_pause"] = "on_pause";
|
||||||
|
H265PlayerConstants["on_resume"] = "on_resume";
|
||||||
|
H265PlayerConstants["on_dispose"] = "on_dispose";
|
||||||
|
H265PlayerConstants["on_error"] = "on_error";
|
||||||
|
H265PlayerConstants["on_player_cb"] = "on_player_cb";
|
||||||
|
})(H265PlayerConstants || (H265PlayerConstants = {}));
|
||||||
|
export class H265Player extends Emittery {
|
||||||
|
/**
|
||||||
|
* @param elemId 播放器元素id
|
||||||
|
* @param maxRetryCount 最大尝试重连次数
|
||||||
|
*/
|
||||||
|
constructor(elemId, maxRetryCount = 3) {
|
||||||
|
super();
|
||||||
|
this.timer = 0;
|
||||||
|
this.currentUrl = '';
|
||||||
|
this.elemId = elemId;
|
||||||
|
this.maxRetryCount = maxRetryCount <= 0 ? 3 : maxRetryCount;
|
||||||
|
this.retryCount = this.maxRetryCount;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
init() {
|
||||||
|
if (this.player) {
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
logger.verbose('init player ~');
|
||||||
|
this.player = new WasmPlayer(null, this.elemId, this.playerCbFunc.bind(this), {
|
||||||
|
Height: true,
|
||||||
|
HideKbs: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
play(url) {
|
||||||
|
var _a;
|
||||||
|
if (!url) {
|
||||||
|
logger.fatal('url is not valid');
|
||||||
|
this.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.ok('start to play ~');
|
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
(_a = this.player) === null || _a === void 0 ? void 0 : _a.play(url, 1);
|
||||||
|
this.currentUrl = url;
|
||||||
|
this.startUrlHeartBeat();
|
||||||
|
}
|
||||||
|
pause() {
|
||||||
|
var _a;
|
||||||
|
logger.warn('player pause');
|
||||||
|
this.emit(H265PlayerConstants.on_pause);
|
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
(_a = this.player) === null || _a === void 0 ? void 0 : _a.destroy();
|
||||||
|
this.player = null;
|
||||||
|
this.stopUrlHeartBeat();
|
||||||
|
}
|
||||||
|
resume() {
|
||||||
|
logger.info('player resume');
|
||||||
|
this.emit(H265PlayerConstants.on_resume);
|
||||||
|
this.init();
|
||||||
|
this.play(this.currentUrl);
|
||||||
|
}
|
||||||
|
playerCbFunc(type) {
|
||||||
|
logger.info('player cb function:', type);
|
||||||
|
this.emit(H265PlayerConstants.on_player_cb, type);
|
||||||
|
switch (type) {
|
||||||
|
case 'play':
|
||||||
|
this.emit(H265PlayerConstants.on_play);
|
||||||
|
this.player.endLoading();
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
this.emit(H265PlayerConstants.on_stop);
|
||||||
|
break;
|
||||||
|
case 'endLoading':
|
||||||
|
this.emit(H265PlayerConstants.on_endLoading);
|
||||||
|
break;
|
||||||
|
case 'pause':
|
||||||
|
this.emit(H265PlayerConstants.on_pause);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeUrl(newUrl) {
|
||||||
|
logger.info('change url');
|
||||||
|
this.dispose();
|
||||||
|
this.init();
|
||||||
|
this.play(newUrl);
|
||||||
|
}
|
||||||
|
dispose() {
|
||||||
|
var _a;
|
||||||
|
logger.warn('dispose player');
|
||||||
|
this.stopUrlHeartBeat();
|
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
(_a = this.player) === null || _a === void 0 ? void 0 : _a.destroy();
|
||||||
|
this.player = null;
|
||||||
|
this.currentUrl = '';
|
||||||
|
this.retryCount = this.maxRetryCount;
|
||||||
|
this.emit(H265PlayerConstants.on_dispose);
|
||||||
|
}
|
||||||
|
stopUrlHeartBeat() {
|
||||||
|
logger.warn('stop url alive heartbeat');
|
||||||
|
if (this.timer) {
|
||||||
|
window.clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startUrlHeartBeat() {
|
||||||
|
this.stopUrlHeartBeat();
|
||||||
|
const url = this.currentUrl;
|
||||||
|
if (!url) {
|
||||||
|
logger.fatal('start url heart beat failed , because of url is not ok, url is:', url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const HEART_BEAT_TIMEOUT = 6 * 1000; // 每隔多少秒进行一次心跳检测
|
||||||
|
logger.verbose(`start url alive heartbeat, every ${HEART_BEAT_TIMEOUT} seconds`);
|
||||||
|
checkUrlIsValid(url)
|
||||||
|
.then(() => {
|
||||||
|
logger.ok('url heartbeat ok, prepare for next heartbeat ~');
|
||||||
|
// 如果正常,开始下一次检测
|
||||||
|
this.timer = window.setTimeout(() => {
|
||||||
|
this.startUrlHeartBeat();
|
||||||
|
}, HEART_BEAT_TIMEOUT);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
if (e.status === 501) {
|
||||||
|
logger.fatal(e.statusText);
|
||||||
|
this.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.retryCount--;
|
||||||
|
logger.fatal('url heartbeat failed with', e);
|
||||||
|
if (this.retryCount <= 0) {
|
||||||
|
logger.warn('reach max retry count, will dispose player ');
|
||||||
|
this.emit(H265PlayerConstants.on_error, e);
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.info('left retry count is: ', `${this.retryCount} / ${this.maxRetryCount} (left / total)`);
|
||||||
|
logger.info('retry heartbeat ...');
|
||||||
|
this.timer = window.setTimeout(() => {
|
||||||
|
this.startUrlHeartBeat();
|
||||||
|
}, HEART_BEAT_TIMEOUT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 检测一个 URL 是否能够正常访问
|
||||||
|
* @param url 要测试的 url
|
||||||
|
* @param timeout 超时时间
|
||||||
|
* @returns 是否能够正常访问
|
||||||
|
*/
|
||||||
|
const checkUrlIsValid = (url, timeout = 5 * 1000) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!isValidURL(url) && !url.includes('m3u8')) {
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
|
return reject({
|
||||||
|
status: 501,
|
||||||
|
statusText: 'url is not valid'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
axios
|
||||||
|
.get(`${url}&__time=${Date.now()}`, {
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout
|
||||||
|
})
|
||||||
|
.then(resolve)
|
||||||
|
.catch(e => {
|
||||||
|
if (e.response) {
|
||||||
|
const { status, statusText } = e.response || {};
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
|
reject({ status, statusText });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
|
reject({
|
||||||
|
status: 500,
|
||||||
|
statusText: (e === null || e === void 0 ? void 0 : e.message) || 'network error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 检查一个url是否合法
|
||||||
|
* @param url 待检查的 url
|
||||||
|
* @returns 是否合法
|
||||||
|
*/
|
||||||
|
export const isValidURL = (url) => {
|
||||||
|
const res = url.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g);
|
||||||
|
return res !== null;
|
||||||
|
};
|
|
@ -46,7 +46,7 @@
|
||||||
<div v-for="(it, idx) in dataTable" :key="idx" class="data-item"
|
<div v-for="(it, idx) in dataTable" :key="idx" class="data-item"
|
||||||
:class="it.timeout ? 'time-out' : ''">
|
:class="it.timeout ? 'time-out' : ''">
|
||||||
<div class="item-left">
|
<div class="item-left">
|
||||||
<el-image ref="preview" style="width: 200px; height: 100px" :preview-src-list="[it.marksPicture]"
|
<el-image ref="preview" style="width: 400px; " :preview-src-list="[it.marksPicture]"
|
||||||
:src="it.marksPicture + '.min.jpg'">
|
:src="it.marksPicture + '.min.jpg'">
|
||||||
</el-image>
|
</el-image>
|
||||||
</div>
|
</div>
|
||||||
|
@ -334,7 +334,8 @@ export default {
|
||||||
|
|
||||||
.item-left {
|
.item-left {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: 200px;
|
width: 400px;
|
||||||
|
min-height: 220px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +354,7 @@ export default {
|
||||||
.item-right {
|
.item-right {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
width: calc(100% - 214px);
|
width: calc(100% - 414px);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.sp-lbl {
|
.sp-lbl {
|
||||||
|
@ -375,7 +376,7 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: solid 1px rgba(255, 255, 255, 0.1);
|
border-bottom: solid 1px rgba(255, 255, 255, 0.1);
|
||||||
line-height: 32px;
|
line-height: 36px;
|
||||||
|
|
||||||
.div-text {
|
.div-text {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -4,6 +4,8 @@ import dayjs from 'dayjs'
|
||||||
import './style/index.less'
|
import './style/index.less'
|
||||||
import dayfilter from '@/utils/dayfilter'
|
import dayfilter from '@/utils/dayfilter'
|
||||||
import {tryToJson} from '../utils/tools'
|
import {tryToJson} from '../utils/tools'
|
||||||
|
import H265Player from '../components/h265-player/index'
|
||||||
|
H265Player.install(Vue);
|
||||||
dayfilter(Vue);
|
dayfilter(Vue);
|
||||||
Vue.prototype.$api=Api;
|
Vue.prototype.$api=Api;
|
||||||
Vue.prototype.$bus=new Vue();
|
Vue.prototype.$bus=new Vue();
|
||||||
|
|
|
@ -166,11 +166,11 @@
|
||||||
<span class="nav-unit">%</span>
|
<span class="nav-unit">%</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="acceptance-item" v-for="(it,idx) in acceptanceData" :key="idx" style="cursor: pointer;" @click="doShowChecking(it)">
|
<div class="acceptance-item" v-for="(it,idx) in acceptanceData" :key="idx" style="cursor: pointer;">
|
||||||
<div class="row-1">
|
<div class="row-1">
|
||||||
<div class="div-img">
|
<div class="div-img">
|
||||||
<el-image :src="getProfileImage(it.mainImage)" :preview-src-list="[getBigProfileImage(it.mainImage)]"/></div>
|
<el-image :src="getProfileImage(it.mainImage)" :preview-src-list="getBigProfileImage(it)"/></div>
|
||||||
<div class="div-text" style="width: 65%;">
|
<div class="div-text" style="width: 65%;" @click="doShowChecking(it)">
|
||||||
<div class="row-3">
|
<div class="row-3">
|
||||||
<div v-if="it.checkResult=='1'" class="sp-lbl">验收合格</div>
|
<div v-if="it.checkResult=='1'" class="sp-lbl">验收合格</div>
|
||||||
<div v-if="it.checkResult=='2'" class="sp-err">验收不合格</div>
|
<div v-if="it.checkResult=='2'" class="sp-err">验收不合格</div>
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-5">
|
<div class="row-5" @click="doShowChecking(it)">
|
||||||
验收描述:{{it.intro}}
|
验收描述:{{it.intro}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -196,6 +196,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ProblemmodifyDetail ref="probDlg"></ProblemmodifyDetail>
|
<ProblemmodifyDetail ref="probDlg"></ProblemmodifyDetail>
|
||||||
|
<showCheckingDlg ref="checkDlg"></showCheckingDlg>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -210,9 +211,10 @@ import '../components/rank-chart'
|
||||||
import '../components/idle-list-chart'
|
import '../components/idle-list-chart'
|
||||||
import '../components/people-number'
|
import '../components/people-number'
|
||||||
import ProblemmodifyDetail from './components/ProblemmodifyDetail.vue'
|
import ProblemmodifyDetail from './components/ProblemmodifyDetail.vue'
|
||||||
|
import showCheckingDlg from './quality/showCheckingDlg.vue'
|
||||||
export default {
|
export default {
|
||||||
components:{
|
components:{
|
||||||
ProblemmodifyDetail
|
ProblemmodifyDetail,showCheckingDlg
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -296,7 +298,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
doShowChecking(it){
|
doShowChecking(it){
|
||||||
|
this.$refs.checkDlg.showDialog(it);
|
||||||
},
|
},
|
||||||
checkDetection(n){
|
checkDetection(n){
|
||||||
this.samplingNav=n;
|
this.samplingNav=n;
|
||||||
|
@ -446,11 +448,19 @@ export default {
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
getBigProfileImage(url) {
|
getBigProfileImage(it) {
|
||||||
if (url) {
|
if(it.imageUrls){
|
||||||
return '/jhapi' + url;
|
let tmps= it.imageUrls.split(",").filter(d=>d).map(it=>{
|
||||||
|
return '/jhapi' + it;
|
||||||
|
})
|
||||||
|
if(tmps.length>0){
|
||||||
|
return tmps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return url;
|
if (it.mainImage && it.mainImage.trim()) {
|
||||||
|
return ['/jhapi' + it.mainImage];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -181,10 +181,10 @@ import '../components/staff-survey-chart'
|
||||||
import '../components/classify-bar'
|
import '../components/classify-bar'
|
||||||
import '../components/list-menu'
|
import '../components/list-menu'
|
||||||
import '../components/amplify/shipinguanli/amplify-spjk'
|
import '../components/amplify/shipinguanli/amplify-spjk'
|
||||||
import H265Player from "vue-h265-player";
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
H265Player,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -1364,8 +1364,8 @@ export default {
|
||||||
/** 查询视频配置列表 */
|
/** 查询视频配置列表 */
|
||||||
initVideoMenu() {
|
initVideoMenu() {
|
||||||
let param = {
|
let param = {
|
||||||
deptId:this.dept.id||0,
|
deptId:this.dept?.id||0,
|
||||||
projectId:this.proojectInfo.projectId||0
|
projectId:this.proojectInfo?.projectId||0
|
||||||
};
|
};
|
||||||
listVideoView(param).then((response) => {
|
listVideoView(param).then((response) => {
|
||||||
this.videoListData = response.data;
|
this.videoListData = response.data;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<MyDialog v-if="show" v-model="show" :width="fontSize==2?'1200px':'1000px'" height="600px" :class="'font-size-' + fontSize"
|
<MyDialog v-if="show" v-model="show" :width="fontSize == 2 ? '1000px' : '1000px'" height="600px"
|
||||||
class="show-checking-dlg">
|
:class="'font-size-' + fontSize" class="show-checking-dlg">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div style="display: flex; align-items: center;justify-content: space-between;">
|
<div style="display: flex; align-items: center;justify-content: space-between;">
|
||||||
<div :key="elKey" class="header-title">
|
<div :key="elKey" class="header-title">
|
||||||
{{ prj.projectName }} - 保险详情
|
{{ row.projectName }} - 举牌验收
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,41 +40,59 @@
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main-content scroll" style="max-height: 780px;overflow-y: auto;">
|
<div class="main-content scroll" style="max-height: 515px;overflow-y: auto;display: flex;">
|
||||||
<div class="data-item" v-for="(it,idx) in list" :key="idx" style="position:relative;">
|
<div class="data-img" style="width: 50%;">
|
||||||
|
<el-carousel height="500px" v-if="images && images.length > 0">
|
||||||
|
<el-carousel-item v-for="item in images" :key="item">
|
||||||
|
<div style="width: 100%;display: flex;align-items: center;justify-content: center;height: 500px;">
|
||||||
|
<el-image :src="item" style="width:100%" :preview-src-list="images" />
|
||||||
|
</div>
|
||||||
|
</el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
</div>
|
||||||
|
<div class="data-content" style="width: 50%;">
|
||||||
|
<div><img src="images/title_icon.png"><span class="sp-lbl">质量专员</span></div>
|
||||||
|
<div class="div-text ">
|
||||||
|
<div>{{ row.qualityUserName }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<table class="data-table">
|
<div><img src="images/title_icon.png"><span class="sp-lbl">监理专员</span></div>
|
||||||
<tr>
|
<div class="div-text ">
|
||||||
<td style="width:50%">部门名称:{{it.deptName }}</td>
|
<div>{{ row.superviseUserName }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<td>保险公司:{{it.companyName }}</td>
|
<div><img src="images/title_icon.png"><span class="sp-lbl">工序部位</span></div>
|
||||||
|
<div class="div-text ">
|
||||||
|
<div>{{ row.checkWorkingPosition }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</tr>
|
<div><img src="images/title_icon.png"><span class="sp-lbl">验收描述</span></div>
|
||||||
<tr>
|
<div class="div-text ">
|
||||||
<td>保险类型:{{ it.insuranceTypeName }}</td>
|
<div>{{ row.intro }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<td>保险单号:{{it.insuranceNumber }}</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>保险状态:
|
<div><img src="images/title_icon.png"><span class="sp-lbl">验收时间</span></div>
|
||||||
<template v-if="it.insuranceState=='Y'">
|
<div class="div-text ">
|
||||||
<i class="el-icon-success" style="color:rgb(34, 193, 52)"></i> <span style="color:rgb(34, 193, 52)">已办理</span>
|
<div>{{ row.checkingDate }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div><img src="images/title_icon.png"><span class="sp-lbl">验收结果</span></div>
|
||||||
|
<div class="div-text ">
|
||||||
|
<div>
|
||||||
|
<template v-if="row.checkResult=='1'">
|
||||||
|
<i class="el-icon-success" style="color:rgb(34, 193, 52)"></i> <span style="color:rgb(34, 193, 52)">合格</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<i class="el-icon-error" style="color:rgb(245, 34, 45)"></i> <span style="color:rgb(245, 34, 45)">未办理</span>
|
<i class="el-icon-error" style="color:rgb(245, 34, 45)"></i> <span style="color:rgb(245, 34, 45)">不合格</span>
|
||||||
</template>
|
</template>
|
||||||
<span v-if="it.insuranceFile" @click="download(it)" style="cursor:pointer;margin-left:12px;color:rgb(1, 169, 255);">
|
</div>
|
||||||
<i class="el-icon-paperclip" style=""></i><span >下载</span>
|
</div>
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>办理时间:{{it.createTime|formatDateTime}}</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</MyDialog>
|
</MyDialog>
|
||||||
|
@ -92,7 +110,8 @@ export default {
|
||||||
elKey: 0,
|
elKey: 0,
|
||||||
fontSize: 0,
|
fontSize: 0,
|
||||||
show: false,
|
show: false,
|
||||||
row:null
|
row: null,
|
||||||
|
images: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -101,11 +120,28 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
download(it){
|
download(it) {
|
||||||
window.open(it.insuranceFile)
|
window.open(it.insuranceFile)
|
||||||
},
|
},
|
||||||
showDialog(row) {
|
showDialog(row) {
|
||||||
this.row=row;
|
this.row = row;
|
||||||
|
this.images = this.getBigProfileImage(row);
|
||||||
|
this.show = true;
|
||||||
|
|
||||||
|
},
|
||||||
|
getBigProfileImage(it) {
|
||||||
|
if (it.imageUrls) {
|
||||||
|
let tmps = it.imageUrls.split(",").filter(d => d).map(it => {
|
||||||
|
return '/jhapi' + it;
|
||||||
|
})
|
||||||
|
if (tmps.length > 0) {
|
||||||
|
return tmps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (it.mainImage && it.mainImage.trim()) {
|
||||||
|
return ['/jhapi' + it.mainImage];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -113,7 +149,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.show-checking-dlg{
|
.show-checking-dlg {
|
||||||
|
|
||||||
.popup-project-introduction-min {
|
.popup-project-introduction-min {
|
||||||
transform: translateY(200px);
|
transform: translateY(200px);
|
||||||
|
@ -126,9 +162,18 @@ export default {
|
||||||
|
|
||||||
.popup-project-introduction-details {
|
.popup-project-introduction-details {
|
||||||
.main-content {
|
.main-content {
|
||||||
|
align-items:start;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
line-height: 64px;
|
line-height: 64px;
|
||||||
|
.data-content{
|
||||||
|
line-height: 48px;
|
||||||
|
.div-text{
|
||||||
|
margin-left:48px;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
top:0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.head-title-tab {
|
.head-title-tab {
|
||||||
.head-nav {
|
.head-nav {
|
||||||
padding: 12px 36px;
|
padding: 12px 36px;
|
||||||
|
@ -148,7 +193,15 @@ export default {
|
||||||
.main-content {
|
.main-content {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
.data-content{
|
||||||
|
line-height: 36px;
|
||||||
|
.div-text{
|
||||||
|
margin-left:36px;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
.head-title-tab {
|
.head-title-tab {
|
||||||
.head-nav {
|
.head-nav {
|
||||||
padding: 12px 36px;
|
padding: 12px 36px;
|
||||||
|
@ -178,17 +231,22 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
padding-top:20px;
|
padding-top: 20px;
|
||||||
.data-item {
|
align-items: center;
|
||||||
border-bottom: solid 1px #fff;
|
.data-content{
|
||||||
padding: 12px 0px 12px 20px;
|
padding-left: 24px;
|
||||||
box-shadow: inset 7px 0px 11px 5px rgb(36 131 167 / 70%);
|
line-height: 32px;
|
||||||
.data-table{
|
.sp-lbl{
|
||||||
border-collapse:collapse;
|
color: aquamarine;
|
||||||
td{
|
white-space: nowrap;
|
||||||
border-bottom:solid 1px rgba(255,255,255,0.2);
|
}
|
||||||
line-height:48px;
|
.div-text{
|
||||||
}
|
margin-left:24px;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
position: relative;
|
||||||
|
top:3px;
|
||||||
|
width: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,3 +59,42 @@
|
||||||
.hide-scroll{
|
.hide-scroll{
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.bg-date-picker{
|
||||||
|
border:none;
|
||||||
|
background: transparent;
|
||||||
|
.el-range-input{
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.el-range-separator{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-date-picker-pop{
|
||||||
|
color: #eee;
|
||||||
|
.el-picker-panel__sidebar{
|
||||||
|
background: transparent;
|
||||||
|
border-right-color: rgb(1, 169, 255);
|
||||||
|
}
|
||||||
|
.el-date-range-picker__content{
|
||||||
|
.el-date-table {
|
||||||
|
th{
|
||||||
|
border-bottom-color: rgb(1, 169, 255);
|
||||||
|
}
|
||||||
|
td.in-range{
|
||||||
|
div{
|
||||||
|
background-color: #01A9FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.is-left{
|
||||||
|
border-right-color: rgb(1, 169, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.popper__arrow{
|
||||||
|
border-bottom-color:#01A9FF !important;
|
||||||
|
&::after{
|
||||||
|
border-bottom-color:#01A9FF !important;
|
||||||
|
top:0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,14 @@ module.exports = defineConfig({
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
'^/jhapi':'/'
|
'^/jhapi':'/'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'/profile':{
|
||||||
|
target: `http://62.234.3.186/profile/`,
|
||||||
|
//target: `http://127.0.0.1:8090/jhapi`,
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
'^/profile':'/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -1995,13 +1995,6 @@ axios@0.24.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.14.4"
|
follow-redirects "^1.14.4"
|
||||||
|
|
||||||
axios@^0.21.1:
|
|
||||||
version "0.21.4"
|
|
||||||
resolved "https://registry.npmmirror.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
|
||||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
|
||||||
dependencies:
|
|
||||||
follow-redirects "^1.14.0"
|
|
||||||
|
|
||||||
babel-helper-vue-jsx-merge-props@^2.0.0:
|
babel-helper-vue-jsx-merge-props@^2.0.0:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
|
resolved "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
|
||||||
|
@ -3334,7 +3327,7 @@ flatted@^3.1.0:
|
||||||
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||||
|
|
||||||
follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.4:
|
follow-redirects@^1.0.0, follow-redirects@^1.14.4:
|
||||||
version "1.15.2"
|
version "1.15.2"
|
||||||
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||||
|
@ -5965,17 +5958,6 @@ vue-eslint-parser@^8.0.1:
|
||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
|
|
||||||
vue-h265-player@^0.0.24:
|
|
||||||
version "0.0.24"
|
|
||||||
resolved "https://registry.npmmirror.com/vue-h265-player/-/vue-h265-player-0.0.24.tgz#22c15550146767882754165a0fdb8858d8ceeb8b"
|
|
||||||
integrity sha512-yvSmbcCcmTwL2/Z1mr/UDiv0BlE4JoDGCgiqqceziIuErqZZf2Zi29xNKXpODW0P8Up0kxf4UKtkck+lWL13GQ==
|
|
||||||
dependencies:
|
|
||||||
"@easydarwin/easywasmplayer" "^4.0.10"
|
|
||||||
axios "^0.21.1"
|
|
||||||
emittery "^0.8.1"
|
|
||||||
logt "^1.4.1"
|
|
||||||
uuid "^8.3.2"
|
|
||||||
|
|
||||||
vue-hot-reload-api@^2.3.0:
|
vue-hot-reload-api@^2.3.0:
|
||||||
version "2.3.4"
|
version "2.3.4"
|
||||||
resolved "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
|
resolved "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
|
||||||
|
|
Loading…
Reference in New Issue