bug fixed

This commit is contained in:
cxc
2022-11-28 16:44:51 +08:00
parent 647e273c1d
commit 3f75b5b378
40 changed files with 1825 additions and 869 deletions

View File

@ -1,20 +1,15 @@
<template>
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld msg="Welcome to Your Vue.js App" /> -->
<!-- <SiteDetail></SiteDetail> -->
<router-view></router-view>
<!-- <List>123132</List> -->
<CameraList />
</template>
<script>
// import HelloWorld from "./components/HelloWorld.vue";
// import SiteDetail from "./components/site-detail.vue";
// import SiteDetail from "./components/site-detail.vue";
import CameraList from "./components/CameraList.vue";
// import List from "./infinite-list-vue.umd.cjs";
export default {
name: "App",
components: {
// HelloWorld,
// SiteDetail,
CameraList,
},
};
</script>
@ -23,12 +18,4 @@ export default {
#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>

539
src/assets/fonts/demo.css Normal file
View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,280 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3725111" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xeb98;</span>
<div class="name">取消全屏_o</div>
<div class="code-name">&amp;#xeb98;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb5e;</span>
<div class="name">播放_o</div>
<div class="code-name">&amp;#xeb5e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb6c;</span>
<div class="name">暂停_o</div>
<div class="code-name">&amp;#xeb6c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb99;</span>
<div class="name">全屏_o</div>
<div class="code-name">&amp;#xeb99;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1666600319624') format('woff2'),
url('iconfont.woff?t=1666600319624') format('woff'),
url('iconfont.ttf?t=1666600319624') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-quxiaoquanping_o"></span>
<div class="name">
取消全屏_o
</div>
<div class="code-name">.icon-quxiaoquanping_o
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-bofang_o"></span>
<div class="name">
播放_o
</div>
<div class="code-name">.icon-bofang_o
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zanting_o"></span>
<div class="name">
暂停_o
</div>
<div class="code-name">.icon-zanting_o
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-quanping_o"></span>
<div class="name">
全屏_o
</div>
<div class="code-name">.icon-quanping_o
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-quxiaoquanping_o"></use>
</svg>
<div class="name">取消全屏_o</div>
<div class="code-name">#icon-quxiaoquanping_o</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-bofang_o"></use>
</svg>
<div class="name">播放_o</div>
<div class="code-name">#icon-bofang_o</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zanting_o"></use>
</svg>
<div class="name">暂停_o</div>
<div class="code-name">#icon-zanting_o</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-quanping_o"></use>
</svg>
<div class="name">全屏_o</div>
<div class="code-name">#icon-quanping_o</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -0,0 +1,31 @@
@font-face {
font-family: "iconfont"; /* Project id 3725111 */
src: url('iconfont.woff2?t=1666600319624') format('woff2'),
url('iconfont.woff?t=1666600319624') format('woff'),
url('iconfont.ttf?t=1666600319624') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-quxiaoquanping_o:before {
content: "\eb98";
}
.icon-bofang_o:before {
content: "\eb5e";
}
.icon-zanting_o:before {
content: "\eb6c";
}
.icon-quanping_o:before {
content: "\eb99";
}

View File

@ -0,0 +1 @@
window._iconfont_svg_string_3725111='<svg><symbol id="icon-quxiaoquanping_o" viewBox="0 0 1024 1024"><path d="M354.133333 682.666667H256v-42.666667h170.666667v170.666667H384v-98.133334L243.2 853.333333l-29.866667-29.866666L354.133333 682.666667z m358.4 0l140.8 140.8-29.866666 29.866666-140.8-140.8V810.666667h-42.666667v-170.666667h170.666667v42.666667h-98.133334zM354.133333 384L213.333333 243.2l29.866667-29.866667L384 354.133333V256h42.666667v170.666667H256V384h98.133333z m358.4 0H810.666667v42.666667h-170.666667V256h42.666667v98.133333L823.466667 213.333333l29.866666 29.866667L712.533333 384z" fill="#444444" ></path></symbol><symbol id="icon-bofang_o" viewBox="0 0 1024 1024"><path d="M533.333333 896C332.8 896 170.666667 733.866667 170.666667 533.333333S332.8 170.666667 533.333333 170.666667 896 332.8 896 533.333333 733.866667 896 533.333333 896z m0-42.666667c174.933333 0 320-145.066667 320-320S708.266667 213.333333 533.333333 213.333333 213.333333 358.4 213.333333 533.333333 358.4 853.333333 533.333333 853.333333z m149.333334-320L469.333333 682.666667V384l213.333334 149.333333z m-68.266667 0L512 460.8v145.066667l102.4-72.533334z" fill="#444444" ></path></symbol><symbol id="icon-zanting_o" viewBox="0 0 1024 1024"><path d="M533.333333 896C332.8 896 170.666667 733.866667 170.666667 533.333333S332.8 170.666667 533.333333 170.666667 896 332.8 896 533.333333 733.866667 896 533.333333 896z m0-42.666667c174.933333 0 320-145.066667 320-320S708.266667 213.333333 533.333333 213.333333 213.333333 358.4 213.333333 533.333333 358.4 853.333333 533.333333 853.333333zM469.333333 426.666667v213.333333h-42.666666v-213.333333h42.666666z m170.666667 0v213.333333h-42.666667v-213.333333h42.666667z" fill="#444444" ></path></symbol><symbol id="icon-quanping_o" viewBox="0 0 1024 1024"><path d="M285.866667 810.666667H384v42.666666H213.333333v-170.666666h42.666667v98.133333l128-128 29.866667 29.866667-128 128z m494.933333 0l-128-128 29.866667-29.866667 128 128V682.666667h42.666666v170.666666h-170.666666v-42.666666h98.133333zM285.866667 256l128 128-29.866667 29.866667-128-128V384H213.333333V213.333333h170.666667v42.666667H285.866667z m494.933333 0H682.666667V213.333333h170.666666v170.666667h-42.666666V285.866667l-128 128-29.866667-29.866667 128-128z" fill="#444444" ></path></symbol></svg>',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var o,i,l,d,a,c=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}o=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_3725111,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?c(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(l=o,d=n.document,a=!1,v(),d.onreadystatechange=function(){"complete"==d.readyState&&(d.onreadystatechange=null,s())})}function s(){a||(a=!0,l())}function v(){try{d.documentElement.doScroll("left")}catch(t){return void setTimeout(v,50)}s()}}(window);

View File

@ -0,0 +1,37 @@
{
"id": "3725111",
"name": "screen",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "5387942",
"name": "取消全屏_o",
"font_class": "quxiaoquanping_o",
"unicode": "eb98",
"unicode_decimal": 60312
},
{
"icon_id": "5387806",
"name": "播放_o",
"font_class": "bofang_o",
"unicode": "eb5e",
"unicode_decimal": 60254
},
{
"icon_id": "5387839",
"name": "暂停_o",
"font_class": "zanting_o",
"unicode": "eb6c",
"unicode_decimal": 60268
},
{
"icon_id": "5387948",
"name": "全屏_o",
"font_class": "quanping_o",
"unicode": "eb99",
"unicode_decimal": 60313
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,270 @@
<template>
<div class="app-container">
<select
name="pets"
v-model="queryParams.query"
id="proj-select"
@change="projectClicked"
>
<option value="">请选择项目</option>
<option v-for="item in projectList" :value="item.PROID">
{{ item.PRONAME }}
</option>
</select>
<div
v-if="queryParams.query && cameraList.length"
class="camera-list"
ref="cameraListRef"
>
<camera
v-for="(item, index) in cameraList"
:key="index"
:name="item.address"
:source="item.flvUrl"
></camera>
</div>
<div v-else-if="queryParams.query && !total">
<div class="image-list">
<!-- <div class="image-item">
<img
src="https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF"
alt=""
/>
</div>
<div class="image-item">
<img
src="https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF"
alt=""
/>
</div> -->
<div class="image-item" v-for="item in imageList" :key="item">
<img :src="`${protocol}//${host}/portal/r/${item}`" alt="" />
</div>
</div>
</div>
<div v-else class="empty">
<img src="../assets/empty.png" alt="" />
请选择项目
</div>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
import camera from "./camera.vue";
import axios from "axios";
const cameraLoading = ref(true);
const projectList = ref([]);
const cameraList = ref([]);
const imageList = ref([]);
const total = ref(0);
const protocol = ref("");
protocol.value = location.protocol;
const host = ref("");
host.value = location.host;
const queryParams = reactive({
cmd: "com.awspaas.user.apps.cmp_camera_list",
pageNum: 1,
pageSize: 10,
sid: sid,
query: "",
});
const loadProjectList = async () => {
// const resp = await axios.get(`http://localhost:3000/project-list`);
const resp = await axios.get(
"./jd?cmd=com.awspaas.user.apps.cmp_screen_getProjectList&sid=" + sid
);
return resp.data;
};
const projectClicked = () => {
// activeIndex.value = index;
// const proid = ;
// queryParams.query = proid;
queryParams.pageNum = 1;
loadCameraList();
};
const loadCameraList = async () => {
cameraLoading.value = true;
const resp = await axios(`./jd`, {
params: queryParams,
});
cameraList.value = resp.data.rows;
total.value = resp.data.total;
cameraLoading.value = false;
if (total.value == 0) {
const rep = await axios.get(
`./jd?cmd=com.awspaas.user.apps.cmp_photo_list&sid=${sid}&proId=${queryParams.query}`
); // 摄像头列表为空时,获取图片列表
imageList.value = rep.data;
}
};
const cameraListRef = ref();
// 滚动操作
const handleScroll = (e) => {
console.log(e);
if (!cameraListRef.value) return;
let dom = document.documentElement;
//文档内容实际高度(包括超出视窗的溢出部分)
let scrollHeight = Math.max(dom.scrollHeight, dom.scrollHeight);
//滚动条滚动距离
let scrollTop = dom.scrollTop;
//窗口可视范围高度
let clientHeight =
dom.innerHeight || Math.min(dom.clientHeight, dom.clientHeight);
console.log(clientHeight, scrollTop, scrollHeight);
if (clientHeight + scrollTop >= scrollHeight) {
if (queryParams.pageSize * queryParams.pageNum > total.value) return;
if (cameraLoading.value) return;
queryParams.pageNum++;
loadCameraList();
console.log("到底了");
}
};
window.addEventListener("scroll", handleScroll, true);
loadProjectList().then((data) => {
projectList.value = data;
if (projectList.value.length) return projectList.value[0].PROID;
});
// .then((proid) => {
// queryParams.query = proid;
// queryParams.pageNum = 1;
// loadCameraList();
// });
</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;
}
.camera-list {
// margin-top: 108px;
padding: 0px 20px 0px;
}
.image-list {
padding: 0px 20px 0px;
.image-item {
margin-bottom: 20px;
// border-radius: 10px;
// overflow: hidden;
img {
border-radius: 10px;
object-fit: cover;
height: 420px;
width: 710px;
}
}
}
// .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 {
// // margin-top: 108px;
// padding: 0px 20px 0px;
// }
// // .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;
// // }
// }
// }
#proj-select {
border: none;
box-shadow: 0 0 0 1px #dcdfe6 inset;
height: 10vw;
border-radius: 1vw;
margin: 2vw 2vw 5vw 2vw;
outline: none;
}
.empty {
// flex: 1;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 80%;
}
// height:80vh;
}
</style>

View File

@ -1,368 +0,0 @@
<template>
<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 {
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;
}
}
}
#proj-select {
border: none;
box-shadow: 0 0 0 1px #dcdfe6 inset;
height: 10vw;
border-radius: 1vw;
margin: 2vw 2vw 5vw 2vw;
outline: none;
}
.empty {
// flex: 1;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 80%;
}
// height:80vh;
}
</style>

View File

@ -3,29 +3,39 @@
<div class="camera-name">
{{ props.name }}
</div>
<video class="camera-player"></video>
<video class="camera-player" ref="previewVideoRef"></video>
<div class="overlay" @click="openPlayModal">
<img src="../assets/stLine-play-l@3x.png" alt="" width="40" height="40" />
<!-- <img src="../assets/stLine-play-l@3x.png" alt="" width="40" height="40" /> -->
<span class="iconfont icon-bofang_o" style="font-size: 60px"></span>
</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 v-if="showModal" class="modal-overlay" @click="closePlayModal">
<span
class="quit-fullscreen iconfont icon-quxiaoquanping_o"
@click.stop="exitFullscreen"
v-if="isFullscreen"
></span>
<div :class="`modal`" ref="rotateElementRef">
<video
:class="`camera-player ${isFullscreen ? 'fullscreen-video' : ''}`"
ref="videoElementRef"
></video>
<div class="video-overlay" @click.stop="switchPlayStatus">
<div
class="iconfont icon-quanping_o fullscreen"
v-if="!isFullscreen"
@click.stop="videoFullscreen"
></div>
</div>
</div>
</div>
</div>
</template>
<script setup name="camera">
import { nextTick, onMounted, ref } from "vue";
import { nextTick, onMounted, onUnmounted, ref } from "vue";
import flvjs from "flv.js";
import { useRoute } from "vue-router";
import axios from "axios";
// import { useRoute } from "vue-router";
const props = defineProps({
name: {
type: String,
@ -36,36 +46,73 @@ const props = defineProps({
"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 route = useRoute();
// document.title = route.query.proname;
const showModal = ref(false);
let flvPlayer;
// const previewVideoRef = ref();
// onMounted(() => {
// const flvPlayer = flvjs.createPlayer({
// type: "flv",
// url: props.source,
// isLive: true,
// });
// flvPlayer.attachMediaElement(previewVideoRef.value);
// flvPlayer.load();
// console.log();
// // loadVideo(props.source);
// });
const openPlayModal = () => {
showModal.value = true;
let flvPlayer = flvjs.createPlayer({
type: "flv",
url: props.source,
});
nextTick(() => {
flvPlayer = flvjs.createPlayer({
type: "flv",
url: props.source,
});
if (flvjs.isSupported()) {
console.log("load");
flvPlayer.attachMediaElement(videoElementRef.value);
// flvPlayer.attachMediaElement();
flvPlayer.load();
flvPlayer.on("ERROR", flvPlayerEventHandler);
flvPlayer.play();
}
});
};
// file为视频的文件对象可使用 input[file] 进行获取
const loadVideo = async (url) => {
const resp = await axios.get(url);
const file = new File([resp.data], "monitor.flv");
console.log(file);
return new Promise(function (resolve, reject) {
const videoElem = document.createElement("video");
const dataUrl = URL.createObjectURL(file);
// 当前帧的数据是可用的
videoElem.onloadeddata = function () {
resolve(videoElem);
};
videoElem.onerror = function (e) {
console.log(e);
reject("video 后台加载失败");
};
// 设置 auto 预加载数据, 否则会出现截图为黑色图片的情况
videoElem.setAttribute("preload", "auto");
videoElem.src = dataUrl;
});
};
const closePlayModal = () => {
showModal.value = false;
flvPlayer.on("ERROR", flvPlayerEventHandler);
flvPlayer.pause();
flvPlayer.unload();
flvPlayer.detachMediaElement();
flvPlayer.destroy();
flvPlayer = null;
showModal.value = false;
};
const videoElementRef = ref();
const playBtnRef = 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",
@ -84,17 +131,33 @@ const switchPlayStatus = () => {
flvPlayer.pause();
}
};
onMounted(() => {
// if (flvjs.isSupported()) {
// console.log("load");
// flvPlayer.attachMediaElement(videoElementRef.value);
// flvPlayer.load();
// flvPlayer.on("ERROR", flvPlayerEventHandler);
// // flvPlayer.play();
// }
const isFullscreen = ref(false);
const rotateElementRef = ref();
const videoFullscreen = () => {
const scale = screen.availWidth / videoElementRef.value.offsetHeight;
videoElementRef.value.style.setProperty("--scale", scale);
isFullscreen.value = true;
};
const exitFullscreen = () => {
isFullscreen.value = false;
};
onUnmounted(() => {
console.log("destroy player here");
function flvDestroy() {
flvPlayer.off("ERROR", flvPlayerEventHandler);
flvPlayer.pause();
flvPlayer.unload();
flvPlayer.detachMediaElement();
flvPlayer.destroy();
flvPlayer = null;
}
if (flvPlayer) {
flvDestroy();
}
});
</script>
<style lang="scss" scoped>
@import "../assets/fonts/iconfont.css";
.camera-item {
// height: 300px;
background-color: white;
@ -144,6 +207,13 @@ onMounted(() => {
z-index: 999;
// position: relative;
background-color: rgba(153, 153, 153, 0.363);
.quit-fullscreen {
position: fixed;
font-size: 60px;
left: 25px;
bottom: 25px;
z-index: 100;
}
.modal {
position: absolute;
top: 50%;
@ -153,6 +223,31 @@ onMounted(() => {
// height: 60vw;
background-color: #fff;
border-radius: 2vw;
.fullscreen-video {
transform-origin: center;
transform: scale(var(--scale)) rotate(90deg);
}
.video-overlay {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
// display: flex;
// align-items: center;
// justify-content: center;
// z-index: 99;
// position: relative;
.fullscreen {
position: absolute;
z-index: 99;
right: 10px;
bottom: 10px;
font-size: 60px;
color: #777;
}
}
}
}
}

16
src/infinite-list-vue.js Normal file
View File

@ -0,0 +1,16 @@
import { openBlock as r, createElementBlock as s, renderSlot as _ } from "vue";
const l = (t, e) => {
const o = t.__vccOpts || t;
for (const [c, n] of e)
o[c] = n;
return o;
}, a = {}, i = { class: "scroll-wrap" };
function d(t, e) {
return r(), s("div", i, [
_(t.$slots, "default")
]);
}
const p = /* @__PURE__ */ l(a, [["render", d]]);
export {
p as List
};

View File

@ -0,0 +1 @@
(function(e,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(e=typeof globalThis<"u"?globalThis:e||self,t(e["infinite-list"]={},e.Vue))})(this,function(e,t){"use strict";const l="",c=(n,s)=>{const i=n.__vccOpts||n;for(const[f,_]of s)i[f]=_;return i},r={},u={class:"scroll-wrap"};function d(n,s){return t.openBlock(),t.createElementBlock("div",u,[t.renderSlot(n.$slots,"default")])}const o=c(r,[["render",d]]);e.List=o,e.default=o,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});

View File

@ -2,8 +2,8 @@ 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";
// import { createWebHashHistory, createRouter } from "vue-router";
import './assets/fonts/iconfont.css'
// const Home = { template: "<div>Home</div>" };
// const About = { template: "<div>About</div>" };
@ -11,18 +11,18 @@ import { createWebHashHistory, createRouter } from "vue-router";
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: "/", component: () => import("./components/HelloWorld.vue") },
{ path: "/detail", component: () => import("./components/site-detail.vue") },
];
// 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` 的缩写
});
// const router = createRouter({
// // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
// history: createWebHashHistory(),
// routes, // `routes: routes` 的缩写
// });
createApp(App).use(router).mount("#app");
createApp(App).mount("#app");