This commit is contained in:
quantulr
2022-10-20 23:55:57 +08:00
parent c107757016
commit 647e273c1d
26 changed files with 1380 additions and 83 deletions

View File

@ -1,26 +1,34 @@
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld msg="Welcome to Your Vue.js App" /> -->
<!-- <SiteDetail></SiteDetail> -->
<router-view></router-view>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
// import HelloWorld from "./components/HelloWorld.vue";
// import SiteDetail from "./components/site-detail.vue";
// import SiteDetail from "./components/site-detail.vue";
export default {
name: 'App',
name: "App",
components: {
HelloWorld
}
}
// HelloWorld,
// SiteDetail,
},
};
</script>
<style>
#app {
background-color: #f6f6f6;
}
/* #app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
} */
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

BIN
src/assets/empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,58 +1,368 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
<div class="app-container">
<!-- <div
class="navbar"
style="width: 750px; height: 100px; background-color: indianred"
></div> -->
<!-- <div class="page-top">
<u-navbar
title="视频监控"
placeholder
bgColor="transparent"
:leftIcon="null"
titleStyle="color:white"
>
</u-navbar>
<div class="search-bar">
<u--input
placeholder="请输入摄像头名称"
prefixIcon="search"
prefixIconStyle="font-size: 32px;color: #909399"
>
</u--input>
</div>
</div> -->
<!-- <div class="sized-box" style="height: var(--status-bar-height)"></div> -->
<!-- <van-nav-bar title="视频监控" left-text="返回" left-arrow /> -->
<!-- <div class="nav-bar">
<div class="center-title">视频监控</div>
</div> -->
<!-- <div class="sized-box" style="height: 60px"></div> -->
<!-- <van-field></van-field> -->
<select name="pets" v-model="proid" id="proj-select">
<option value="">请选择项目</option>
<option v-for="item in projectList" :value="item.id">
{{ item.name }}
</option>
</select>
<div v-if="proid" class="site-list">
<!-- <navigator url="/pages/monitor/site-detail/site-detail"> -->
<div
class="site-item"
v-for="item in siteList"
:key="item.id"
@click="routerGo"
>
<div class="site-title">
<text>{{ item.name }}</text>
</div>
<div class="camera-list">
<div
class="camera-item"
v-for="(cameraItem, index) in item.camera_list"
:key="index"
>
<img
class="camera-image"
src="../assets/camera_example.png"
mode=""
/>
<div class="camera-title">
{{ cameraItem.name }}
</div>
</div>
</div>
<div class="site-time">
<text>{{ item.time }}</text>
</div>
</div>
<!-- </navigator> -->
</div>
<div v-else class="empty">
<img src="../assets/empty.png" alt="" />
请选择项目
</div>
</div>
</template>
<script>
// import { Field, CellGroup } from 'vant';
// import { NavBar, Field } from "vant";
// import { query } from "express";
// import { router } from "vue-router";
export default {
name: 'HelloWorld',
props: {
msg: String
components: {
// [NavBar.name]: NavBar,
// [Field.name]: Field,
},
mounted() {},
data() {
return {
proid: "",
projectList: [
{
name: "测试办公楼扩建",
id: 1,
},
{
name: "项目二",
id: 2,
},
{
name: "项目三",
id: 3,
},
],
siteList: [
{
id: 1,
name: "项目场地1",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 2,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 3,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 4,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 5,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 6,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 7,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
{
id: 8,
name: "项目场地2",
time: "2022-09-12 12:12:12",
camera_list: [
{
name: "camera1",
},
{
name: "camera1",
},
{
name: "camera1",
},
],
},
],
};
},
methods: {
routerGo() {
console.log("detail");
// this.$router.push("/detail");
this.$router.push({
path: "/detail",
query: {
proname: this.projectList.find((el) => el.id == this.proid).name,
},
});
// router.push("/detail");
// uni.navigateTo({
// url: "/pages/monitor/site-detail/site-detail",
// });
},
},
};
</script>
<style>
/* body {
background-color: #f6f6f6;
} */
</style>
<style scoped lang="scss">
.app-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.nav-bar {
width: 750px;
height: 88px;
background: linear-gradient(to top right, #496df6, #2e9ee8);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 32px;
position: fixed;
}
.site-list {
flex: 1;
margin-top: 20px;
padding-bottom: 28px;
.site-item {
margin-left: 16px;
margin-right: 16px;
border-radius: 8px;
background-color: #fff;
&:not(:last-child) {
margin-bottom: 40px;
}
.site-title {
background-color: #949494;
width: 120px;
height: 40px;
line-height: 20px;
border-radius: 8px 0px 18px 0px;
display: flex;
justify-content: center;
align-items: center;
text {
font-family: YSBiaoTiHei-regular;
color: white;
font-size: 20px;
}
}
.camera-list {
padding: 0 20px 0;
margin-top: 12px;
white-space: nowrap;
// width: 100%;
display: flex;
justify-content: space-between;
.camera-item {
// background-color: aquamarine;
.camera-image {
width: 200px;
height: 140px;
}
.camera-title {
font-size: 20px;
text-align: center;
}
}
}
.site-time {
padding-right: 20px;
margin-top: 26px;
border-radius: 0 0 8px 8px;
text-align: right;
height: 30px;
font-size: 20px;
color: #fff;
background-color: #d7d7d7;
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
#proj-select {
border: none;
box-shadow: 0 0 0 1px #dcdfe6 inset;
height: 10vw;
border-radius: 1vw;
margin: 2vw 2vw 5vw 2vw;
outline: none;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
.empty {
// flex: 1;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 80%;
}
// height:80vh;
}
</style>

159
src/components/camera.vue Normal file
View File

@ -0,0 +1,159 @@
<template>
<div class="camera-item">
<div class="camera-name">
{{ props.name }}
</div>
<video class="camera-player"></video>
<div class="overlay" @click="openPlayModal">
<img src="../assets/stLine-play-l@3x.png" alt="" width="40" height="40" />
</div>
<div v-if="showModal" class="modal-overlay" @click="showModal = false">
<div class="modal">
<video class="camera-player" ref="videoElementRef"></video>
<div class="overlay" @click.stop="switchPlayStatus">
<!-- <img
src="../assets/stLine-play-l@3x.png"
alt=""
width="40"
height="40"
/> -->
</div>
</div>
</div>
</div>
</template>
<script setup name="camera">
import { nextTick, onMounted, ref } from "vue";
import flvjs from "flv.js";
import { useRoute } from "vue-router";
const props = defineProps({
name: {
type: String,
},
source: {
type: String,
default:
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
},
});
const route = useRoute();
document.title = route.query.proname;
const showModal = ref(false);
const openPlayModal = () => {
showModal.value = true;
let flvPlayer = flvjs.createPlayer({
type: "flv",
url: props.source,
});
nextTick(() => {
if (flvjs.isSupported()) {
console.log("load");
flvPlayer.attachMediaElement(videoElementRef.value);
flvPlayer.load();
flvPlayer.on("ERROR", flvPlayerEventHandler);
flvPlayer.play();
}
});
};
const closePlayModal = () => {
showModal.value = false;
flvPlayer.on("ERROR", flvPlayerEventHandler);
flvPlayer.pause();
flvPlayer.unload();
flvPlayer.detachMediaElement();
flvPlayer.destroy();
flvPlayer = null;
};
const videoElementRef = ref();
const playBtnRef = ref();
// let flvPlayer = flvjs.createPlayer({
// type: "flv",
// url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
// });
const flvPlayerEventHandler = (e) => {
console.log(e);
};
// 切换播放状态
const switchPlayStatus = () => {
if (!videoElementRef.value) return;
if (videoElementRef.value.paused) {
console.log(flvPlayer);
flvPlayer.play();
} else {
flvPlayer.pause();
}
};
onMounted(() => {
// if (flvjs.isSupported()) {
// console.log("load");
// flvPlayer.attachMediaElement(videoElementRef.value);
// flvPlayer.load();
// flvPlayer.on("ERROR", flvPlayerEventHandler);
// // flvPlayer.play();
// }
});
</script>
<style lang="scss" scoped>
.camera-item {
// height: 300px;
background-color: white;
border-radius: 10px;
margin-bottom: 20px;
position: relative;
.camera-name {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
background-color: #c6c6c6;
border-radius: 10px 0 10px 0;
color: white;
top: 0;
left: 0;
font-size: 20px;
height: 50px;
width: 160px;
z-index: 99;
}
.camera-player {
width: 100%;
height: 400px;
border-radius: 10px;
}
.overlay {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
z-index: 99;
}
.modal-overlay {
width: 100vw;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 999;
// position: relative;
background-color: rgba(153, 153, 153, 0.363);
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90vw;
// height: 60vw;
background-color: #fff;
border-radius: 2vw;
}
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<div>
<div class="camera-list">
<camera
v-for="(item, index) in cameraList"
:key="index"
:name="item.name"
:source="item.source"
></camera>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import camera from "./camera.vue";
const cameraList = ref([
{
name: "CAMERA01",
source:
"http://101.34.251.155:10000/sms/34020000002020000001/flv/hls/34020000001320000001_34020000001320000002.flv",
},
{
name: "CAMERA02",
},
{
name: "CAMERA03",
},
{
name: "CAMERA04",
},
{
name: "CAMERA06",
},
{
name: "CAMERA07",
},
]);
// const videoElementRef = ref();
// const playBtnRef = ref();
// let flvPlayer = flvjs.createPlayer({
// type: "flv",
// url: "https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
// // url: "http://localhost:8000/lycoris_recoil.flv",
// });
// const flvPlayerEventHandler = (e) => {
// console.log(e);
// };
// onMounted(() => {
// if (flvjs.isSupported()) {
// flvPlayer.attachMediaElement(videoElementRef.value);
// flvPlayer.load();
// flvPlayer.on("ERROR", flvPlayerEventHandler);
// // flvPlayer.play();
// }
// });
</script>
<style>
page {
background-color: #f6f6f6;
}
</style>
<style lang="scss" scoped>
.nav-bar {
top: 0;
width: 750px;
z-index: 9999;
height: 88px;
background: linear-gradient(to top right, #496df6, #2e9ee8);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 32px;
position: fixed;
}
.camera-list {
// margin-top: 108px;
padding: 0px 20px 0px;
}
</style>

View File

@ -1,4 +1,28 @@
import { createApp } from 'vue'
import App from './App.vue'
import { createApp } from "vue";
// import "vant/lib/index.css";
import App from "./App.vue";
import "modern-normalize/modern-normalize.css";
import { createWebHashHistory, createRouter } from "vue-router";
// import { apply } from "core-js/fn/reflect";
createApp(App).mount('#app')
// const Home = { template: "<div>Home</div>" };
// const About = { template: "<div>About</div>" };
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: "/", component: () => import("./components/HelloWorld.vue") },
{ path: "/detail", component: () => import("./components/site-detail.vue") },
];
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
});
createApp(App).use(router).mount("#app");