Compare commits

...

5 Commits

Author SHA1 Message Date
cxc
a9e70a6642 yarn berry 2023-02-14 15:50:05 +08:00
cxc
825c43ddca 1:1 view in mobile 2023-02-14 15:16:05 +08:00
cxc
c526f39dc2 format and fix label position 2023-02-14 10:38:52 +08:00
cxc
d67091c17c redirect 2022-11-09 17:26:49 +08:00
cxc
e22463f589 nuoyun 2022-11-07 16:44:14 +08:00
22 changed files with 10940 additions and 6971 deletions

8
.gitignore vendored
View File

@ -21,3 +21,11 @@ pnpm-debug.log*
*.njsproj
*.sln
*.sw?
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

View File

@ -1,11 +1,15 @@
/* 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');
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 {
@ -48,7 +52,6 @@
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
@ -215,35 +218,35 @@
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
.markdown > p,
.markdown > blockquote,
.markdown > .highlight,
.markdown > ol,
.markdown > ul {
width: 80%;
}
.markdown ul>li {
.markdown ul > li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
.markdown > ul li,
.markdown blockquote ul > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
.markdown > ul li p,
.markdown > ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
.markdown ol > li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
.markdown > ol li,
.markdown blockquote ol > li {
margin-left: 20px;
padding-left: 4px;
}
@ -260,7 +263,7 @@
font-weight: 600;
}
.markdown>table {
.markdown > table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
@ -269,21 +272,21 @@
margin-bottom: 24px;
}
.markdown>table th {
.markdown > table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
.markdown > table th,
.markdown > table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
.markdown > table th {
background: #f7f7f7;
}
.markdown blockquote {
@ -318,12 +321,11 @@
display: inline-block;
}
.markdown>br,
.markdown>p>br {
.markdown > br,
.markdown > p > br {
clear: both;
}
.hljs {
display: block;
background: white;
@ -404,7 +406,7 @@ pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
@ -439,7 +441,6 @@ code[class*="language-"] ::selection {
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
@ -449,19 +450,19 @@ code[class*="language-"] ::selection {
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
margin: 0.5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
:not(pre) > code[class*="language-"] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
@ -477,7 +478,7 @@ pre[class*="language-"] {
}
.namespace {
opacity: .7;
opacity: 0.7;
}
.token.property,
@ -505,7 +506,7 @@ pre[class*="language-"] {
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
background: hsla(0, 0%, 100%, 0.5);
}
.token.atrule,
@ -516,7 +517,7 @@ pre[class*="language-"] {
.token.function,
.token.class-name {
color: #DD4A68;
color: #dd4a68;
}
.token.regex,

View File

@ -1,81 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.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;
}
<head>
<meta charset="utf-8" />
<title>iconfont Demo</title>
<link
rel="shortcut icon"
href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico"
type="image/x-icon"
/>
<link
rel="icon"
type="image/svg+xml"
href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.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 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=3446052" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
.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=3446052"
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">&#xe63d;</span>
<div class="name">横屏</div>
<div class="code-name">&amp;#xe63d;</div>
</li>
<div class="name">横屏</div>
<div class="code-name">&amp;#xe63d;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<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"
<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=1654150368956') format('woff2'),
@ -83,8 +109,8 @@
url('iconfont.ttf?t=1654150368956') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
@ -93,82 +119,99 @@
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<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>
<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-hengping"></span>
<div class="name">
横屏
</div>
<div class="code-name">.icon-hengping
</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">
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-hengping"></use>
</svg>
<div class="name">横屏</div>
<div class="code-name">#icon-hengping</div>
<span class="icon iconfont icon-hengping"></span>
<div class="name">横屏</div>
<div class="code-name">.icon-hengping</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<h2 id="font-class-">font-class 引用</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;
<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="-css-">第二步:加入通用 CSS 代码(引入一次就行)</h3>
<pre><code class="language-html">&lt;style&gt;
<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-hengping"></use>
</svg>
<div class="name">横屏</div>
<div class="code-name">#icon-hengping</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;
@ -178,34 +221,33 @@
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
<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>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
<script>
$(document).ready(function () {
$(".tab-container .content:first").show();
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
$("#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')
if ($(this).hasClass("active")) {
return;
} else {
$("#tabs li").removeClass("active");
$(this).addClass("active");
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
tabContent.hide().eq(index).fadeIn();
}
});
});
</script>
</body>
</html>

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3446052 */
src: url('iconfont.woff2?t=1654150368956') format('woff2'),
url('iconfont.woff?t=1654150368956') format('woff'),
url('iconfont.ttf?t=1654150368956') format('truetype');
src: url("iconfont.woff2?t=1654150368956") format("woff2"),
url("iconfont.woff?t=1654150368956") format("woff"),
url("iconfont.ttf?t=1654150368956") format("truetype");
}
.iconfont {
@ -16,4 +16,3 @@
.icon-hengping:before {
content: "\e63d";
}

View File

@ -1 +1,65 @@
!function(e){var t,n,c,o,i,d='<svg><symbol id="icon-hengping" viewBox="0 0 1024 1024"><path d="M924.23621932 877.12193043H535.08765856c-53.6870912-0.02761681-97.21119393-43.48267751-97.22500236-97.10072668V99.88805635c0.01380842-53.61804916 43.53791115-97.08691826 97.22500236-97.10072666h389.02428509c53.70089962 0 97.23881076 43.46886912 97.25261916 97.10072666V780.02120375a96.8784113 96.8784113 0 0 1-28.40389573 68.68302254 97.11867762 97.11867762 0 0 1-68.75206459 28.41770414h0.02761683z m24.27518166-752.86203354c0-26.85735402-21.78966818-48.61940537-48.67463901-48.61940537H559.48711591c-26.88497083 0-48.67463902 21.76205138-48.67463901 48.61940537v461.40796103h437.69892408V124.25989689z m0 534.27493126H510.8124769v97.10072667c0 26.85735402 21.78966818 48.61940537 48.67463901 48.61940537h340.47392174c26.85735402 0 48.6470222-21.76205138 48.64702219-48.61940537v-97.10072667h-0.09665886z m-218.84946205 121.4725672a48.6470222 48.6470222 0 0 1-42.14326192-24.26137327 48.56555259 48.56555259 0 0 1-0.04142522-48.59178857 48.66497312 48.66497312 0 0 1 42.1156451-24.31660688c26.87116241-0.02761681 48.6608306 21.72062615 48.67463901 48.55036333 0.02761681 26.8435456-21.73443455 48.60559698-48.60559697 48.61940539zM140.42954293 274.55061207c16.21107126-27.98964348 40.01676705-63.28393491 71.38947055-94.58759639 64.48526643-64.45764962 150.34594882-107.04278061 150.34594881-107.0427806 13.40796438-14.38836139 13.00752055-36.79940794-0.91135494-50.6906666-13.9188755-13.89125869-36.35753887-14.27789411-50.75970865-0.86992973-14.38836139 13.40796438-82.72617371 45.44347149-147.36333263 109.95635474-35.91566981 35.92947822-65.89372406 77.36851132-85.61213105 107.27752354l-60.28751033-34.3829365v194.33953745l194.57428038-83.23708482-71.36185374-40.73480427-0.0138084-0.02761682z m-43.01319164 165.39711378h243.12464372c13.03513737 0 25.07606935 6.94562933 31.59363802 18.21329047 6.51756868 11.26766112 6.51756868 25.1589198 0 36.4265809s-18.55850066 18.21329046-31.59363802 18.21329045H121.69153296c-26.85735402 0-48.6470222 21.76205138-48.64702221 48.6194054v340.05966948c0 26.82973718 21.74824297 48.59178857 48.64702221 48.59178856h656.54838613c13.46319803 0 24.30279849-10.93625932 24.30279849-24.24756486 0-13.00752055 6.94562933-25.03464412 18.24090727-31.5522128a36.54533323 36.54533323 0 0 1 36.48181454 0 36.39758325 36.39758325 0 0 1 18.24090728 31.5522128c-0.02761681 53.63185757-43.55171956 97.11453508-97.25261917 97.11453508H97.38873447c-53.6870912-0.02761681-97.19738554-43.48267751-97.22500235-97.11453508V537.04845253c0.01380842-53.61804916 43.53791115-97.08691826 97.22500235-97.10072668h0.02761682z m0 0" fill="#2c2c2c" ></path></symbol></svg>',l=(l=document.getElementsByTagName("script"))[l.length-1].getAttribute("data-injectcss"),a=function(e,t){t.parentNode.insertBefore(e,t)};if(l&&!e.__iconfont__svg__cssinject__){e.__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(e){console&&console.log(e)}}function s(){i||(i=!0,c())}function r(){try{o.documentElement.doScroll("left")}catch(e){return void setTimeout(r,50)}s()}t=function(){var e,t=document.createElement("div");t.innerHTML=d,d=null,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(e=document.body).firstChild?a(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),t()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(c=t,o=e.document,i=!1,r(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,s())})}(window);
!(function (e) {
var t,
n,
c,
o,
i,
d =
'<svg><symbol id="icon-hengping" viewBox="0 0 1024 1024"><path d="M924.23621932 877.12193043H535.08765856c-53.6870912-0.02761681-97.21119393-43.48267751-97.22500236-97.10072668V99.88805635c0.01380842-53.61804916 43.53791115-97.08691826 97.22500236-97.10072666h389.02428509c53.70089962 0 97.23881076 43.46886912 97.25261916 97.10072666V780.02120375a96.8784113 96.8784113 0 0 1-28.40389573 68.68302254 97.11867762 97.11867762 0 0 1-68.75206459 28.41770414h0.02761683z m24.27518166-752.86203354c0-26.85735402-21.78966818-48.61940537-48.67463901-48.61940537H559.48711591c-26.88497083 0-48.67463902 21.76205138-48.67463901 48.61940537v461.40796103h437.69892408V124.25989689z m0 534.27493126H510.8124769v97.10072667c0 26.85735402 21.78966818 48.61940537 48.67463901 48.61940537h340.47392174c26.85735402 0 48.6470222-21.76205138 48.64702219-48.61940537v-97.10072667h-0.09665886z m-218.84946205 121.4725672a48.6470222 48.6470222 0 0 1-42.14326192-24.26137327 48.56555259 48.56555259 0 0 1-0.04142522-48.59178857 48.66497312 48.66497312 0 0 1 42.1156451-24.31660688c26.87116241-0.02761681 48.6608306 21.72062615 48.67463901 48.55036333 0.02761681 26.8435456-21.73443455 48.60559698-48.60559697 48.61940539zM140.42954293 274.55061207c16.21107126-27.98964348 40.01676705-63.28393491 71.38947055-94.58759639 64.48526643-64.45764962 150.34594882-107.04278061 150.34594881-107.0427806 13.40796438-14.38836139 13.00752055-36.79940794-0.91135494-50.6906666-13.9188755-13.89125869-36.35753887-14.27789411-50.75970865-0.86992973-14.38836139 13.40796438-82.72617371 45.44347149-147.36333263 109.95635474-35.91566981 35.92947822-65.89372406 77.36851132-85.61213105 107.27752354l-60.28751033-34.3829365v194.33953745l194.57428038-83.23708482-71.36185374-40.73480427-0.0138084-0.02761682z m-43.01319164 165.39711378h243.12464372c13.03513737 0 25.07606935 6.94562933 31.59363802 18.21329047 6.51756868 11.26766112 6.51756868 25.1589198 0 36.4265809s-18.55850066 18.21329046-31.59363802 18.21329045H121.69153296c-26.85735402 0-48.6470222 21.76205138-48.64702221 48.6194054v340.05966948c0 26.82973718 21.74824297 48.59178857 48.64702221 48.59178856h656.54838613c13.46319803 0 24.30279849-10.93625932 24.30279849-24.24756486 0-13.00752055 6.94562933-25.03464412 18.24090727-31.5522128a36.54533323 36.54533323 0 0 1 36.48181454 0 36.39758325 36.39758325 0 0 1 18.24090728 31.5522128c-0.02761681 53.63185757-43.55171956 97.11453508-97.25261917 97.11453508H97.38873447c-53.6870912-0.02761681-97.19738554-43.48267751-97.22500235-97.11453508V537.04845253c0.01380842-53.61804916 43.53791115-97.08691826 97.22500235-97.10072668h0.02761682z m0 0" fill="#2c2c2c" ></path></symbol></svg>',
l = (l = document.getElementsByTagName("script"))[
l.length - 1
].getAttribute("data-injectcss"),
a = function (e, t) {
t.parentNode.insertBefore(e, t);
};
if (l && !e.__iconfont__svg__cssinject__) {
e.__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 (e) {
console && console.log(e);
}
}
function s() {
i || ((i = !0), c());
}
function r() {
try {
o.documentElement.doScroll("left");
} catch (e) {
return void setTimeout(r, 50);
}
s();
}
(t = function () {
var e,
t = document.createElement("div");
(t.innerHTML = d),
(d = null),
(t = t.getElementsByTagName("svg")[0]) &&
(t.setAttribute("aria-hidden", "true"),
(t.style.position = "absolute"),
(t.style.width = 0),
(t.style.height = 0),
(t.style.overflow = "hidden"),
(t = t),
(e = document.body).firstChild ? a(t, e.firstChild) : e.appendChild(t));
}),
document.addEventListener
? ~["complete", "loaded", "interactive"].indexOf(document.readyState)
? setTimeout(t, 0)
: ((n = function () {
document.removeEventListener("DOMContentLoaded", n, !1), t();
}),
document.addEventListener("DOMContentLoaded", n, !1))
: document.attachEvent &&
((c = t),
(o = e.document),
(i = !1),
r(),
(o.onreadystatechange = function () {
"complete" == o.readyState && ((o.onreadystatechange = null), s());
}));
})(window);

View File

@ -0,0 +1 @@
<!-- <template></template> -->

View File

@ -9,6 +9,7 @@
import dayjs from "dayjs";
import duration from "dayjs/plugin/duration";
import { onMounted, onUnmounted, ref } from "vue";
dayjs.extend(duration);
const emit = defineEmits(["timeup"]);
@ -26,7 +27,6 @@ onMounted(() => {
timer = setInterval(() => {
durationTime.value =
new Date(props.startTime).getTime() - new Date().getTime();
console.log(durationTime.value);
if (durationTime.value <= 0 && durationTime.value >= -1200) {
emit("timeup");
}

View File

@ -74,7 +74,7 @@ const { messageList } = toRefs(props);
:deep(p) {
margin: 0;
word-wrap: break-word;
word-break:break-all;
word-break: break-all;
}
}
.time {

View File

@ -1,75 +1,75 @@
<template>
<div class="text-tooltip">
<el-tooltip
class="item"
effect="dark"
:disabled="isShowTooltip"
:content="content"
placement="top"
>
<p class="over-flow" :class="className" @mouseover="onMouseOver(refName)">
<span :ref="refName">{{ content || '-' }}</span>
</p>
</el-tooltip>
</div>
<div class="text-tooltip">
<el-tooltip
class="item"
effect="dark"
:disabled="isShowTooltip"
:content="content"
placement="top"
>
<p class="over-flow" :class="className" @mouseover="onMouseOver(refName)">
<span :ref="refName">{{ content || "-" }}</span>
</p>
</el-tooltip>
</div>
</template>
<script>
export default {
name: 'textTooltip',
props: {
// 显示的文字内容
content: {
type: String,
default: () => {
return ''
}
},
// 外层框的样式,在传入的这个类名中设置文字显示的宽度
className: {
type: String,
default: () => {
return ''
}
},
// 为页面文字标识(如在同一页面中调用多次组件,此参数不可重复)
refName: {
type: String,
default: () => {
return ''
}
}
name: "textTooltip",
props: {
// 显示的文字内容
content: {
type: String,
default: () => {
return "";
},
},
data() {
return {
isShowTooltip: true
}
// 外层框的样式,在传入的这个类名中设置文字显示的宽度
className: {
type: String,
default: () => {
return "";
},
},
methods: {
onMouseOver(str) {
let parentWidth = this.$refs[str].parentNode.offsetWidth;
let contentWidth = this.$refs[str].offsetWidth;
// 判断是否开启tooltip功能
if (contentWidth > parentWidth) {
this.isShowTooltip = false;
} else {
this.isShowTooltip = true;
}
}
}
}
// 为页面文字标识(如在同一页面中调用多次组件,此参数不可重复)
refName: {
type: String,
default: () => {
return "";
},
},
},
data() {
return {
isShowTooltip: true,
};
},
methods: {
onMouseOver(str) {
let parentWidth = this.$refs[str].parentNode.offsetWidth;
let contentWidth = this.$refs[str].offsetWidth;
// 判断是否开启tooltip功能
if (contentWidth > parentWidth) {
this.isShowTooltip = false;
} else {
this.isShowTooltip = true;
}
},
},
};
</script>
<style lang="scss" scoped>
.over-flow {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.wid190 {
width: 100%;
width: 100%;
}
p {
margin: 0;
margin: 0;
}
</style>

View File

@ -1,7 +1,6 @@
import { createWebHistory, createRouter } from "vue-router";
import store from "@/store";
import _ from "lodash";
import cryptoJs from "crypto-js";
import {
whitelistJoinMeeting,
@ -14,26 +13,6 @@ import dayjs from "dayjs";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/meeting/56',
redirect: '/meeting/90'
},
{
path: "/appointment/56",
redirect: "/appointment/90",
},
{
path: "/verify/56",
redirect: '/verify/90'
},
{
path: "/panelist-verify/56",
redirect: '/panelist-verify/90'
},
{
path: "/panelist/56",
redirect: '/panelist/90'
},
{
path: "/appointment/:meetingId",
name: "Appointment",
@ -54,21 +33,41 @@ const router = createRouter({
name: "Meeting",
component: () => import("@/views/meeting.vue"),
},
{
path: "/meeting-ny/:meetingId",
name: "MeetingNy",
component: () => import("@/views/meeting-test.vue"),
},
{
path: "/panelist/:meetingId",
name: "Panelist",
component: () => import("@/views/meeting.vue"),
},
{
path: "/panelist-ny/:meetingId",
name: "PanelistNy",
component: () => import("@/views/meeting-test.vue"),
},
{
path: "/host/:meetingId/:createEmail/:pwd/:username/:nickname",
name: "Host",
component: () => import("@/views/meeting.vue"),
},
{
path: "/host-ny/:meetingId/:createEmail/:pwd/:username/:nickname",
name: "HostNy",
component: () => import("@/views/meeting-test.vue"),
},
{
path: "/supervisor/:meetingId/:username",
name: "Supervisor",
component: () => import("@/views/meeting.vue"),
},
{
path: "/supervisor-ny/:meetingId/:username",
name: "SupervisorNy",
component: () => import("@/views/meeting-test.vue"),
},
{
path: "/error",
name: "Error",
@ -92,6 +91,7 @@ const router = createRouter({
router.beforeEach(async (to) => {
await store.dispatch("getMeetingSettings");
// 判断会议信息是否存在,不存在则请求数据
if (!store.state.meeting.id && to.params.meetingId) {
await store.dispatch("getMeetingInfo", to.params.meetingId);
}
@ -138,7 +138,7 @@ router.beforeEach(async (to) => {
return true;
}
// 如果要前往参会页面
else if (to.name === "Meeting") {
else if (to.name === "Meeting" || to.name === "MeetingNy") {
// 如果要去的页面会议号于 vuex中的不一样则清除数据
// if (to.params.meetingId !== store.state.joinUser.meetingId) {
// store.commit("setJoinUser", {});
@ -153,7 +153,7 @@ router.beforeEach(async (to) => {
store.commit("setLiked", false);
store.commit("setMessagesList", []);
store.commit("setJoinType", store.state.meeting.joinType);
return `/verify/${to.params.meetingId}`;
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
}
if (store.state.meeting.joinType === "1") {
// 如果是白名单模式
@ -175,20 +175,20 @@ router.beforeEach(async (to) => {
store.commit("setJoinUser", {});
store.commit("setLiked", false);
store.commit("setMessagesList", []);
return `/verify/${to.params.meetingId}`;
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
}
} else {
store.commit("setJoinUser", {});
store.commit("setLiked", false);
store.commit("setMessagesList", []);
return `/verify/${to.params.meetingId}`;
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
}
} else {
if (_.isEmpty(store.state.joinUser)) {
store.commit("setJoinUser", {});
store.commit("setLiked", false);
store.commit("setMessagesList", []);
return `/verify/${to.params.meetingId}`;
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
} else {
if (store.state.meeting.joinType === "2") {
const { meetingPassword, email } = await registerJoinUser(
@ -237,13 +237,13 @@ router.beforeEach(async (to) => {
store.commit("setJoinUser", {});
store.commit("setLiked", false);
store.commit("setMessagesList", []);
return `/panelist-verify/${to.params.meetingId}`;
return `/panelist-verify/${to.params.meetingId}?redirect=${to.path}`;
}
} else {
store.commit("setJoinUser", {});
store.commit("setLiked", false);
store.commit("setMessagesList", []);
return `/panelist-verify/${to.params.meetingId}`;
return `/panelist-verify/${to.params.meetingId}?redirect=${to.path}`;
}
} else if (to.name === "Supervisor") {
// 监管参会
@ -262,6 +262,8 @@ router.beforeEach(async (to) => {
});
store.commit("setPassword", meetingPassword);
return true;
} else if (to.name === "MeetingNy") {
return true;
}
});

View File

@ -32,8 +32,8 @@ const store = createStore({
localStorage.setItem("JOIN_USER", JSON.stringify(data));
},
setTempUser(state, data) {
state.tempUser = data
localStorage.setItem("TEMP_USER", JSON.stringify(data))
state.tempUser = data;
localStorage.setItem("TEMP_USER", JSON.stringify(data));
},
// 设置会议信息
setMeetingInfo(state, data) {

View File

@ -0,0 +1,26 @@
@media only screen and (min-width: 768px) {
.meeting-title {
font-size: 24px;
}
.meeting-cover {
height: 47vh;
display: block;
margin: 0 auto;
}
.meeting-time {
font-size: 16px;
}
.form-container {
width: 80%;
margin: 0 auto;
}
.form-container .joinuser-wrap {
justify-content: space-between;
}
.form-container .joinuser-wrap .joinuser-item {
width: 36%;
}
.form-container .joinuser-wrap .joinuser-item :deep(.el-form-item__label) {
width: 150px;
}
}

26
src/style/appoint-desktop.min.css vendored Normal file
View File

@ -0,0 +1,26 @@
@media only screen and (min-width: 768px) {
.meeting-title {
font-size: 24px;
}
.meeting-cover {
height: 47vh;
display: block;
margin: 0 auto;
}
.meeting-time {
font-size: 16px;
}
.form-container {
width: 80%;
margin: 0 auto;
}
.form-container .joinuser-wrap {
justify-content: space-between;
}
.form-container .joinuser-wrap .joinuser-item {
width: 36%;
}
.form-container .joinuser-wrap .joinuser-item :deep(.el-form-item__label) {
width: 150px;
}
}

View File

@ -12,11 +12,13 @@
font-size: 16px;
}
.form-container {
padding: 0 10px 0;
// padding: 0 10px 0;
width: 80%;
margin: 0 auto;
.joinuser-wrap {
justify-content: space-between;
.joinuser-item {
width: 46%;
width: 36%;
:deep(.el-form-item__label) {
width: 150px;
}

View File

@ -1 +1,30 @@
@media only screen and (max-width: 768px){.meeting-cover{width:100%;display:block;margin:0 auto}.meeting-title{font-size:7vw}.meeting-time{flex-direction:column;align-items:center;font-size:5vw}.meeting-time .title{margin-right:3vw}.meeting-time :not(:last-child){margin-right:0px}.form-container{padding:0 2vw 0}.form-container .joinuser-item{width:100%}.form-container .joinuser-item :deep(.el-form-item__label){width:70px}}
@media only screen and (max-width: 768px) {
.meeting-cover {
width: 100%;
display: block;
margin: 0 auto;
}
.meeting-title {
font-size: 7vw;
}
.meeting-time {
flex-direction: column;
align-items: center;
font-size: 5vw;
}
.meeting-time .title {
margin-right: 3vw;
}
.meeting-time :not(:last-child) {
margin-right: 0px;
}
.form-container {
padding: 0 2vw 0;
}
.form-container .joinuser-item {
width: 100%;
}
.form-container .joinuser-item :deep(.el-form-item__label) {
width: 70px;
}
}

View File

@ -1,6 +1,6 @@
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}
401: "认证失败,无法访问系统资源",
403: "当前操作没有权限",
404: "访问资源不存在",
default: "系统未知错误,请反馈给管理员",
};

562
src/views/meeting-test.vue Normal file
View File

@ -0,0 +1,562 @@
<template>
<div id="app-container" ref="appContainerRef">
<div id="meeting-chat-row">
<div id="meeting-container" ref="meetingContainerRef">
<iframe
ref="nuoyunIfrRef"
id="nuoyun-iframe"
src="https://console.nuoyun.tv/PlayerEmbed/PlayerEmbed.html?type=1&appid=639920665"
scrolling="no"
frameborder="0"
allowFullScreen
></iframe>
<div id="text-label-wrap">
<div
:id="`tag-${item.uniqId}`"
:key="item.uniqId"
class="text-tag"
v-for="item in labelList"
v-html="item.textLabel.content"
:style="{
left: `${item.textLabel.x}%`,
top: `${item.textLabel.y}%`,
backgroundColor: item.textLabel.backgroundColor,
visibility:
item.textLabel.visibility === '1' ? 'visible' : 'hidden',
}"
></div>
</div>
</div>
<div id="chat-container" ref="chatContainerRef">
<Chat
:is-host="route.name === 'Host'"
place="right"
:account="joinName"
:message-list="messages"
@send="sendMessage"
/>
</div>
</div>
<div :class="`like-row`">
<like
:meeting-id="store.getters.meetingId"
:like="likeCount"
:online="onlineCount"
style="margin: 0 auto"
/>
</div>
<el-tabs class="tabs" type="border-card">
<el-tab-pane label="会议介绍">
<div class="meeting-info meeting-note" v-html="meetingNote"></div>
</el-tab-pane>
<el-tab-pane label="会议日程"
><div
class="meeting-info meeting-schedule"
v-html="meetingSchedule"
></div
></el-tab-pane>
<el-tab-pane label="专家介绍"
><div class="meeting-info expert-info" v-html="expertInfo"></div
></el-tab-pane>
<el-tab-pane label="聊天" class="chat-pane" v-if="screenWidth <= 768">
<Chat
:is-host="route.name === 'Host'"
place="bottom"
:account="joinName"
:message-list="messages"
@send="sendMessage"
/>
</el-tab-pane>
<el-tab-pane
label="考核"
v-if="route.name === 'Meeting' || route.name === 'MeetingNy'"
>
<!-- // 签到、考试、问卷弹窗 -->
<el-row :gutter="10">
<el-col :span="12"
><el-button
type="primary"
:disabled="
!isDuringExamPeriod || store.state.joinUser.examSubmited
"
@click="showExamDialog = true"
style="width: 100%"
>考试</el-button
></el-col
>
<el-col :span="12"
><el-button
type="primary"
style="width: 100%"
@click="showQuestionnaireDialog = true"
:disabled="
!isDuringQuestionnairePeriod ||
store.state.joinUser.questionnaireSubmited
"
>问卷</el-button
></el-col
>
</el-row>
</el-tab-pane>
</el-tabs>
<el-dialog
v-model="showSignDialog"
:close-on-click-modal="false"
title="签到"
width="30%"
:fullscreen="screenWidth < 900"
>
<span>是否确认签到</span>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="submitSign">确定</el-button>
<el-button type="primary" @click="showSignDialog = false"
>取消</el-button
>
</span>
</template>
</el-dialog>
<questions
mode="1"
@stage="getStageExamAnswer"
:questions-list="examQuestionsList"
v-if="showExamDialog && route.name !== 'Host'"
:showDialog="showExamDialog"
@close="showExamDialog = $event"
></questions>
<questions
mode="2"
@stage="getStageQuestionnaireAnswer"
:questions-list="questionnaireQuestionsList"
v-if="showQuestionnaireDialog && route.name !== 'Host'"
:showDialog="showQuestionnaireDialog"
@close="showQuestionnaireDialog = $event"
></questions>
</div>
</template>
<script setup>
import { computed, nextTick, onMounted, reactive, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import { uniqueId } from "lodash";
import ReconnectingWebSocket from "reconnecting-websocket";
import dayjs from "dayjs";
import questions from "@/components/questions.vue";
import Chat from "@/components/chat.vue";
import like from "@/components/like.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
signMeeting,
// generateSignature,
getOnlineUserTotalAndLikes,
getQuestionsList,
commitQuestionnaire,
commitExam,
} from "@/api/meeting";
const route = useRoute();
const store = useStore();
const router = useRouter();
const templateId = ref(0);
const meetingNote = computed(() => store.getters.meetingNote); // 会议介绍
const meetingSchedule = computed(() => store.getters.meetingSchedule); // 会议日程
const expertInfo = computed(() => store.getters.expertInfo); // 专家信息
const joinName = ref(""); // 显示聊天昵称
const joinAccount = ref(""); // 用于连接 websocket提交考试
joinAccount.value =
store.getters.username ||
store.getters.icCard ||
store.getters.phone ||
store.getters.nickname;
joinName.value =
store.getters.nickname || store.getters.phone || store.getters.icCard;
const appContainerRef = ref(); // 应用容器
const meetingContainerRef = ref(); // 会议容器
const chatContainerRef = ref(); // 聊天容器
const nuoyunIfrRef = ref(); // 诺云iframe
const screenWidth = ref(0);
screenWidth.value = window.screen.width;
// 初始化尺寸
const initSize = () => {
const pageWidth = document.body.clientWidth;
appContainerRef.value.style.setProperty("--app-width", `${pageWidth}px`);
appContainerRef.value.style.setProperty(
"--meeting-container-width",
`${pageWidth * 0.8}px`
);
appContainerRef.value.style.setProperty(
"--chat-container-width",
`${pageWidth * 0.2}px`
);
};
onMounted(() => {
initSize();
});
/** 加载、设置文本标签 */
const labelList = ref([]);
const loadTextLabelList = () => {
labelList.value = store.getters.textLabelList.map((el) => {
return {
...el,
textLabel: JSON.parse(el.textLabel),
uniqId: _.uniqueId(),
};
});
};
loadTextLabelList();
/** 进入会议时获取点赞数量和在线人数 */
const onlineCount = ref(0);
const likeCount = ref(0);
const getLikeAndOnline = async () => {
const { data } = await getOnlineUserTotalAndLikes(store.getters.meetingId);
onlineCount.value = data.online;
likeCount.value = data.like;
};
getLikeAndOnline();
/** 从缓存中获取问题答案 */
const examQuestionsList = ref([]);
const getStageExamAnswer = (val) => {
examQuestionsList.value = val.map((el) => el);
};
const questionnaireQuestionsList = ref([]);
const getStageQuestionnaireAnswer = (val) => {
questionnaireQuestionsList.value = val.map((el) => el);
};
/** websocket 连接、监听考试聊天消息 */
let socket = reactive({});
const initWebSocket = () => {
// 建立websocket连接
socket = new ReconnectingWebSocket(
`wss://meeting.chuhuankj.com/wss/websocket/meeting/${store.getters.meetingId}/${joinAccount.value}`
);
socket.addEventListener("open", () => {
console.log("websocket,已连接");
});
// 监听websocket消息
socket.addEventListener("message", async (event) => {
let data;
try {
data = JSON.parse(JSON.parse(event.data));
} catch (error) {
data = JSON.parse(event.data);
}
// 会议信息更新时
if (data.type === "isRefreshMeeting") {
await store.dispatch("getMeetingInfo", store.getters.meetingId);
meetingContainerRef.value.style.background = `url(${
store.getters.templateBackgroundPic || store.getters.defaultBackground
}) 0% 0% / cover no-repeat`;
templateId.value = store.getters.templateId;
loadTextLabelList();
}
// 收到聊天消息时
else if (data.type === "isChat") {
messages.value.push({
...JSON.parse(data.content),
id: uniqueId(),
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
nextTick(() => {
document
.querySelector(".message-list .message-row:last-child")
.scrollIntoView({ behavior: "smooth" });
});
store.commit("setMessagesList", messages.value);
}
// 当检测到敏感词时
else if (data.type === "isSensitive") {
ElMessage.error(`消息未发送成功,因为包含违禁词:${data.content}`);
}
// 开始签到时
else if (data.type === "isStartSign" && route.name === "Meeting") {
showSignDialog.value = true;
}
// 签到结束时
else if (data.type === "isEndSign" && route.name === "Meeting") {
showSignDialog.value = false;
}
// 开始考试时
else if (data.type === "isStartExam" && route.name === "Meeting") {
showExamDialog.value = true;
isDuringExamPeriod.value = true;
}
// 开始问卷时
else if (data.type === "isStartQuestionnaire" && route.name === "Meeting") {
showQuestionnaireDialog.value = true;
isDuringQuestionnairePeriod.value = true;
} else if (data.type === "isRefreshOnlineAndLike") {
getLikeAndOnline();
}
// 当检测到异地登陆时,强制退出登录,并清除数据
else if (data.type === "isRemoteLogin") {
ElMessageBox.alert("您的账号在异地登录,将被强制下线", "异地登录", {
type: "warning",
"show-close": false,
"show-confirm-button": false,
"show-cancel-button": false,
});
setTimeout(() => {
// leaveConference();
store.commit("setJoinUser", {});
store.commit("setPassword", "");
store.commit("setMessagesList", []);
store.commit("setLiked", false);
router.push(
`/verify/${store.getters.meetingId}?redirect=${route.path}`
);
}, 2000);
}
// 会议结束时
else if (data.type === "isCloseMeeting") {
showExamDialog.value = false;
showQuestionnaireDialog.value = false;
isDuringExamPeriod.value = false;
isDuringQuestionnairePeriod.value = false;
ElMessageBox.alert("会议已结束");
socket.close();
if (route.name === "Meeting") {
if (store.getters.bankId && !store.state.joinUser.examSubmited) {
if (examQuestionsList.value.length === 0) {
examQuestionsList.value = await loadQuestionsList("1");
}
submitQuestion("1");
}
if (
store.getters.questionnaireId &&
!store.state.joinUser.questionnaireSubmited
) {
if (questionnaireQuestionsList.value.length === 0) {
questionnaireQuestionsList.value = await loadQuestionsList("2");
}
submitQuestion("2");
}
} else if (route.name === "Host") {
meetingConfig.client.endMeeting();
}
}
});
socket.addEventListener("close", (event) => {
console.log(event, "close");
});
socket.addEventListener("error", (event) => {
console.log(event, "error");
});
};
initWebSocket();
/** 聊天功能 */
const messages = ref([]); // 消息列表
messages.value = store.state.messagesList.map((msg) => msg); // 从缓存读取
const sendMessage = (msgObj) => {
// 发送消息
socket.send(
JSON.stringify({
account: joinName.value,
msg: msgObj.msg,
})
);
messages.value.push(msgObj);
nextTick(() => {
document
.querySelector(".message-list .message-row:last-child")
.scrollIntoView({ behavior: "smooth" });
});
store.commit("setMessagesList", messages.value);
};
/** 签到功能 */
const showSignDialog = ref(false);
const submitSign = async () => {
// 提交签到
await signMeeting({
meetingId: store.getters.meetingId,
signTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
account: joinAccount.value,
});
showSignDialog.value = false;
store.commit("setJoinUser", {
...store.state.joinUser,
signSubmited: true,
});
ElMessage.success("签到成功");
};
/** 考试功能 */
const showExamDialog = ref(false); //是否显示考试弹窗
const showQuestionnaireDialog = ref(false); //是否显示问卷弹窗
const isDuringExamPeriod = ref(false); // 是否在考试时间段内
const isDuringQuestionnairePeriod = ref(false); // 是否在问卷时间段内
isDuringExamPeriod.value = (() => {
const examStartTime = dayjs(store.state.meeting.examStartTime);
const meetingEndTime = dayjs(store.state.meeting.startTime).add(
store.state.meeting.duration,
"minute"
);
if (!examStartTime) {
return false;
} else {
const now = dayjs();
return now.isAfter(examStartTime) && now.isBefore(meetingEndTime);
}
})();
isDuringQuestionnairePeriod.value = (() => {
const questionnaireStartTime = dayjs(
store.state.meeting.questionnaireStartTime
);
const meetingEndTime = dayjs(store.state.meeting.startTime).add(
store.state.meeting.duration,
"minute"
);
if (!questionnaireStartTime) {
return false;
} else {
const now = dayjs();
return now.isAfter(questionnaireStartTime) && now.isBefore(meetingEndTime);
}
})();
/** 当考试和问卷弹框未能正确弹出时,(即考试开始时,未加入会议),加载题目列表 */
const loadQuestionsList = async (mode) => {
const { data } = await getQuestionsList({
meetingId: store.getters.meetingId,
type: mode,
});
return data.map((item) => {
return {
...item,
choiceAnswerIdStr: [],
};
});
};
/** 当会议结束时,如果没有手动点击提交则自动提交试卷 */
const submitQuestion = async (mode) => {
if (mode == "1") {
await commitExam({
meetingId: store.getters.meetingId,
userAccount: joinAccount.value,
commitExamList: examQuestionsList.value.map((item) => {
return {
questionId: item.id,
choiceAnswerIdStr: item.choiceAnswerIdStr.join(",") + ",",
};
}),
});
ElMessage.success("提交考试成功");
} else if (mode == "2") {
await commitQuestionnaire({
meetingId: store.getters.meetingId,
userAccount: joinAccount.value,
commitExamList: questionnaireQuestionsList.value.map((item) => {
return {
questionId: item.id,
choiceAnswerIdStr: item.choiceAnswerIdStr.join(",") + ",",
};
}),
});
ElMessage.success("提交问卷成功");
}
};
</script>
<style lang="scss" scoped>
#app-container {
#meeting-chat-row {
display: flex;
justify-content: center;
#meeting-container {
position: relative;
width: var(--meeting-container-width);
height: calc(var(--meeting-container-width) * 9 / 16);
#nuoyun-iframe {
overflow: hidden;
height: 100%;
width: 100%;
}
#text-label-wrap {
pointer-events: none;
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
:deep(.text-tag) {
position: absolute;
z-index: 999;
border-radius: 4px;
padding: 5px;
background-color: #fff;
* {
pointer-events: none;
margin: 0;
padding: 0;
}
}
}
}
#chat-container {
width: var(--chat-container-width);
height: calc(var(--meeting-container-width) * 9 / 16);
:deep(.chat-container .message-list) {
flex-grow: 1;
overflow-y: scroll;
}
}
}
.like-row {
padding-right: 20vw;
// background-color: #f5f5f5;
}
.tabs {
width: var(--app-width);
margin: 0 auto;
.chat-pane {
display: none;
}
}
}
// 手机样式
@media screen and (max-width: 768px) {
#app-container {
#meeting-chat-row {
#meeting-container {
width: 100vw;
height: calc(100vw * 9 / 16);
#nuoyun-iframe {
height: 100%;
width: 100%;
}
}
#chat-container {
display: none;
}
.tabs {
width: 100vw;
}
}
.like-row {
padding-right: 0;
}
.tabs {
.chat-pane {
display: initial;
}
}
}
}
</style>

View File

@ -3,6 +3,7 @@
id="app-container"
:class="{
isShare: templateId == 5 && inSharing && !isShareByme,
useNuoyun: route.name === 'MeetingNy',
}"
ref="appContainerRef"
>
@ -18,8 +19,20 @@
notInSharing: !inSharing,
}"
>
<div class="text-label-container" ref="textLabelContainerRef"></div>
<div
class="text-label-container"
ref="textLabelContainerRef"
v-if="route.name != 'MeetingNy'"
></div>
<iframe
class="nuoyun-ifr"
allowfullscreen
src="https://console.nuoyun.tv/PlayerEmbed/PlayerEmbed.html?type=1&appid=451264724"
frameborder="0"
v-if="route.name === 'MeetingNy'"
></iframe>
<div
v-else
id="video-element"
:class="`layout-template-${templateId}`"
ref="videoElementRef"
@ -33,13 +46,13 @@
style="position: absolute; bottom: 1vw; right: 6vw"
/> -->
<el-button
v-if="!isFullScreen"
v-if="!isFullScreen && route.name !== 'MeetingNy'"
:icon="FullScreen"
circle
@click="setFullScreen"
></el-button>
<el-button
v-else
v-else-if="isFullScreen && route.name !== 'MeetingNy'"
:icon="CloseBold"
circle
@click="quitFullScreen"
@ -139,7 +152,7 @@
</el-dialog>
<!-- <mediaCheck @close="startMeeting" /> -->
<mediaCheck @close="startMeeting" />
<mediaCheck @close="startMeeting" v-if="route.name != `MeetingNy`" />
<questions
mode="1"
@ -185,7 +198,7 @@ import {
generateSignature,
getOnlineUserTotalAndLikes,
} from "@/api/meeting";
import axios from "axios";
import Chat from "@/components/chat";
import mediaCheck from "@/components/mediaCheck.vue";
import like from "@/components/like.vue";
@ -195,7 +208,6 @@ import {
commitQuestionnaire,
commitExam,
} from "@/api/meeting";
// import CountDown from "@/components/countDown.vue";
const store = useStore();
const route = useRoute();
@ -226,7 +238,7 @@ templateId.value = store.getters.templateId;
/* 会议配置 */
const meetingConfig = reactive({
client: ZoomMtgEmbedded.createClient(),
sdkKey: "TUgbQFx4RhPHDPa0OQAKVgPL2dPGQoVqZIuW",
sdkKey: "0CmUUjvpHS4GqNATCq7x1iwvFopGYTk9CQaS",
meetingNumber: store.getters.meetingNumber,
passWord: store.state.password,
role: route.name === "Host" ? 1 : 0,
@ -356,26 +368,6 @@ const startMeeting = async () => {
}
};
// const setSize = () => {
// meetingWidth.value = meetingContainerRef.value.offsetWidth * 0.88;
// meetingHeight.value = (meetingWidth.value * 9) / 16;
// // videoElementRef.value.style.width = `${meetingWidth.value}px`;
// videoElementRef.value.style.height = `${meetingHeight.value + 42}px`;
// document.querySelector(
// "#video-element> div> .zmwebsdk-MuiPaper-root> .zmwebsdk-MuiPaper-root:nth-child(1)"
// ).style.width = `${meetingWidth.value}px`;
// document
// .querySelectorAll(
// 'div[id*="suspension-view-tabpanel"] > .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root'
// )
// .forEach((el) => {
// el.style.height = `${meetingHeight.value}px`;
// });
// };
// 设置文本标签
const setTextLabel = () => {
document.querySelectorAll(".text-tag").forEach((el) => {
@ -391,8 +383,8 @@ const setTextLabel = () => {
textEl.style.backgroundColor = labelObj.backgroundColor;
textEl.style.visibility =
labelObj.visibility === "1" ? "visible" : "hidden";
textEl.style.left = `${labelObj.x}`;
textEl.style.top = `${labelObj.y}`;
textEl.style.left = `${labelObj.x}%`;
textEl.style.top = `${labelObj.y}%`;
textLabelContainerRef.value.appendChild(textEl);
});
};
@ -455,7 +447,6 @@ setInterval(() => {
`div[class*="zmwebsdk-makeStyles-inSharing"]`
);
inSharing.value = screenShareEl ? true : false;
// ------
// TODO:查找停止共享按钮元素,判断是否由自己共享,由自己共享则不应用 id 5 布局。
if (templateId.value == 5) {
@ -680,13 +671,10 @@ const initWebSocket = () => {
// 监听websocket消息
socket.addEventListener("message", async (event) => {
console.log(JSON.parse(event.data));
console.log(event.data);
let data;
try {
data = JSON.parse(JSON.parse(event.data));
} catch (error) {
console.log(error);
data = JSON.parse(event.data);
}
@ -730,14 +718,13 @@ const initWebSocket = () => {
// 开始考试时
else if (data.type === "isStartExam" && route.name === "Meeting") {
showExamDialog.value = true;
isDuringExamPeriod.value = true;
// isDuringExamPeriod.value = true;
}
// 开始问卷时
else if (data.type === "isStartQuestionnaire" && route.name === "Meeting") {
showQuestionnaireDialog.value = true;
isDuringQuestionnairePeriod.value = true;
} else if (data.type === "isRefreshOnlineAndLike") {
console.log(data.type);
getLikeAndOnline();
}
// 当检测到异地登陆时,强制退出登录,并清除数据
@ -754,7 +741,9 @@ const initWebSocket = () => {
store.commit("setPassword", "");
store.commit("setMessagesList", []);
store.commit("setLiked", false);
router.push(`/verify/${store.getters.meetingId}`);
router.push(
`/verify/${store.getters.meetingId}?redirect=${route.path}`
);
}, 2000);
}
// 会议结束时
@ -930,11 +919,10 @@ $meetingComponentHeight: $meetingComponentWitdh * 9 / 16;
$meetingBackgroundWidth: 80vw; //会议背景宽度
$meetingBackgroundHeight: 80vw * 9 / 16;
// @media screen and (max-width: 900px) {
.like-row.isShare {
margin-top: 42px;
}
// }
.isShare {
.text-label-container {
display: none !important;
@ -1064,6 +1052,7 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
padding-right: 20vw;
background-color: #f5f5f5;
}
#meeting-chat-row {
display: flex;
justify-content: space-between;
@ -1085,7 +1074,6 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
position: relative;
.text-label-container {
position: absolute;
// z-index: -1;
top: 0;
left: 0;
width: $meetingBackgroundWidth;
@ -1126,6 +1114,15 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
}
}
#app-container.useNuoyun {
#meeting-container {
padding-top: 0 !important;
}
.nuoyun-ifr {
width: 80vw;
height: calc(80vw * 9 / 16);
}
}
.layout-template-1 {
:deep(div[id*="suspension-view-tabpanel"]
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
@ -1267,6 +1264,18 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
position: relative;
align-self: initial;
}
&.layout-template-1,
&.layout-template-2 {
:deep(div[id*="suspension-view-tabpanel"]
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
> div[class*="inSharing"]
+ div) {
width: $meetingComponentWitdh * 0.5;
height: $meetingComponentWitdh * 0.5 * 9 / 16;
// align-self: center;
}
}
// width: 72vw;
:deep(div[id*="suspension-view-tabpanel"]
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
@ -1390,6 +1399,7 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
> div) {
width: 88vh;
}
// 竖屏全屏
#meeting-container.verticalFullScreen {
$meetingComponentWitdh: 88vh;
$meetingComponentHeight: $meetingComponentWitdh * 9 / 16;
@ -1414,6 +1424,17 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
width: $meetingComponentWitdh * 0.15;
height: $meetingComponentWitdh * 0.15 * 9 / 14.5;
}
&.layout-template-1,
&.layout-template-2 {
:deep(div[id*="suspension-view-tabpanel"]
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
> div[class*="inSharing"]
+ div) {
width: $meetingComponentWitdh * 0.5;
height: $meetingComponentWitdh * 0.5 * 9 / 14.5;
}
}
:deep(div[id*="suspension-view-tabpanel"]
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
> div[class*="inSharing"]

View File

@ -133,7 +133,9 @@ const submitVerify = async (newJoinUserRef) => {
}
const valid = await newJoinUserRef.validate();
store.commit("setJoinUser", newJoinUser.value);
router.push(`/panelist/${meetingId.value}`);
// router.push(`/panelist/${meetingId.value}`);
router.push(route.query.redirect);
};
const saveTempUser = async (newJoinUserRef) => {

View File

@ -628,19 +628,21 @@ const submitVerify = async (newJoinUserRef) => {
ElMessage.error("请勾选同意用户协议");
return;
}
console.log(meeting.value.joinType);
if (meeting.value.joinType === "1") {
store.commit("setJoinUser", newJoinUser.value);
router.push(`/meeting/${meetingId.value}`);
} else if (meeting.value.joinType === "2") {
store.commit("setJoinUser", newJoinUser.value);
router.push(`/meeting/${meetingId.value}`);
} else if (meeting.value.joinType === "3") {
// const { data } = await visitorJoinUser(newJoinUser.value);
// store.commit("setPassword", data);
store.commit("setJoinUser", newJoinUser.value);
router.push(`/meeting/${meetingId.value}`);
}
store.commit("setJoinUser", newJoinUser.value);
router.push(route.query.redirect);
// console.log(meeting.value.joinType);
// if (meeting.value.joinType === "1") {
// store.commit("setJoinUser", newJoinUser.value);
// router.push(`/meeting/${meetingId.value}`);
// } else if (meeting.value.joinType === "2") {
// store.commit("setJoinUser", newJoinUser.value);
// router.push(`/meeting/${meetingId.value}`);
// } else if (meeting.value.joinType === "3") {
// // const { data } = await visitorJoinUser(newJoinUser.value);
// // store.commit("setPassword", data);
// store.commit("setJoinUser", newJoinUser.value);
// router.push(`/meeting/${meetingId.value}`);
// }
};
const refreshPage = () => {
const state = meeting.value.status == 1 ? true : false;

View File

@ -6,6 +6,13 @@ module.exports = defineConfig({
devServer: {
port: 3000,
// proxy: {
// "/iframe-source": {
// // target: "https://console.nuoyun.tv",
// target: "http://127.0.0.1:9090/",
// changeOrigin: true
// }
// }
// proxy: {
// "/api": {
// target: "http://120.26.107.74:1618",
// // ws: true,

16417
yarn.lock

File diff suppressed because it is too large Load Diff