Sync from bytedesk-private: update

This commit is contained in:
jack ning
2024-12-14 10:43:18 +08:00
parent 476eebb101
commit 5e082909e4
3421 changed files with 812709 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
@use 'sass:math';
@function p($px) {
@return #{math.div($px, 19.2) + 'rem'};
}

View File

@@ -0,0 +1,3 @@
body {
// 全局第三方和公司组件样式覆盖
}

View File

@@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View File

@@ -0,0 +1,4 @@
.ui-jessibuca {
width: 100%;
height: 100%;
}

View File

@@ -0,0 +1,106 @@
<template>
<div class="ui-jessibuca"></div>
</template>
<script>
export default {
name: 'ui-jessibuca',
props: {
videoUrl: {
type: String,
default: ''
},
showBandwidth: {
type: Boolean,
default: true
},
fullscreenFlag: {
type: Boolean,
default: true
},
screenshotFlag: {
type: Boolean,
default: true
},
playFlag: {
type: Boolean,
default: true
},
audioFlag: {
type: Boolean,
default: true
}
},
data () {
return {
jessibuca: null
}
},
watch: {
videoUrl: {
immediate: true,
handler (newVal, oldVal) {
if (newVal) {
this.init()
setTimeout(() => {
this.jessibuca.play(newVal)
}, 100)
} else if (this.jessibuca) {
this.jessibuca.destroy()
this.jessibuca = null
}
}
}
},
created () {},
mounted () {
this.init()
},
beforeDestroy () {
this.jessibuca && this.jessibuca.destroy()
},
methods: {
init () {
const that = this
if (!this.jessibuca && this.$el) {
this.jessibuca = new window.Jessibuca({
container: this.$el,
videoBuffer: 0.2, // 缓存时长
isResize: false,
text: '',
loadingText: '加载中',
debug: false,
useMSE: true, // 开启硬编码
showBandwidth: this.showBandwidth, // 显示网速
controlAutoHide: true,
operateBtns: {
fullscreen: this.fullscreenFlag,
screenshot: this.screenshotFlag,
play: this.playFlag,
audio: this.audioFlag
},
forceNoOffscreen: true,
isNotMute: false
})
this.jessibuca.on('error', function (error) {
console.log('error:', error)
})
this.jessibuca.on('fullscreen', function (flag) {
console.log('is fullscreen', flag)
that.$emit('fullscreen', flag)
})
this.jessibuca.on('webFullscreen', function (flag) {
console.log('is webFullscreen', flag)
that.$emit('webFullscreen', flag)
})
}
},
setFullscreen (flag) {
this.jessibuca.setFullscreen(flag)
}
}
}
</script>
<style src="./assets/css/index.scss" lang="scss"></style>

View File

@@ -0,0 +1,72 @@
.ui-scrollbar {
overflow: hidden;
position: relative;
&.child-over-width {
.ui-scrollbar__view {
max-width: 100%;
}
}
&:active > .ui-scrollbar__bar,
&:focus > .ui-scrollbar__bar,
&:hover > .ui-scrollbar__bar {
opacity: 1;
transition: opacity 0.34s ease-out;
}
}
.ui-scrollbar__wrap {
overflow: scroll;
height: 100%;
}
.ui-scrollbar__view {
display: inline-block;
vertical-align: middle;
min-width: 100%;
}
.ui-scrollbar__bar {
position: absolute;
right: 2px;
bottom: 2px;
z-index: 1;
border-radius: 4px;
opacity: 0;
-webkit-transition: opacity 120ms ease-out;
transition: opacity 120ms ease-out;
&.is-horizontal {
height: 6px;
left: 2px;
& > div {
height: 100%;
}
}
&.is-vertical {
width: 6px;
top: 2px;
& > div {
width: 100%;
}
}
}
.ui-scrollbar__thumb {
position: relative;
display: block;
width: 0;
height: 0;
cursor: pointer;
border-radius: inherit;
background-color: rgba(144, 147, 153, 0.3);
-webkit-transition: 0.3s background-color;
transition: 0.3s background-color;
&:hover {
background-color: hsla(220, 4%, 58%, 0.5);
}
}

View File

@@ -0,0 +1,104 @@
<script>
import { on, off, renderThumbStyle, BAR_MAP } from './util'
export default {
name: 'scrollbar-Bar',
props: {
vertical: Boolean,
size: String,
move: Number
},
computed: {
bar () {
return BAR_MAP[this.vertical ? 'vertical' : 'horizontal']
},
wrap () {
return this.$parent.wrap
}
},
destroyed () {
off(document, 'mouseup', this.mouseUpDocumentHandler)
},
methods: {
clickThumbHandler (e) {
// prevent click event of right button
if (e.ctrlKey || e.button === 2) {
return
}
this.startDrag(e)
this[this.bar.axis] =
e.currentTarget[this.bar.offset] -
(e[this.bar.client] -
e.currentTarget.getBoundingClientRect()[this.bar.direction])
},
clickTrackHandler (e) {
const offset = Math.abs(
e.target.getBoundingClientRect()[this.bar.direction] -
e[this.bar.client]
)
const thumbHalf = this.$refs.thumb[this.bar.offset] / 2
const thumbPositionPercentage =
((offset - thumbHalf) * 100) / this.$el[this.bar.offset]
this.wrap[this.bar.scroll] =
(thumbPositionPercentage * this.wrap[this.bar.scrollSize]) /
100
},
startDrag (e) {
e.stopImmediatePropagation()
this.cursorDown = true
on(document, 'mousemove', this.mouseMoveDocumentHandler)
on(document, 'mouseup', this.mouseUpDocumentHandler)
document.onselectstart = () => false
},
mouseMoveDocumentHandler (e) {
if (this.cursorDown === false) return
const prevPage = this[this.bar.axis]
if (!prevPage) return
const offset =
(this.$el.getBoundingClientRect()[this.bar.direction] -
e[this.bar.client]) *
-1
const thumbClickPosition =
this.$refs.thumb[this.bar.offset] - prevPage
const thumbPositionPercentage =
((offset - thumbClickPosition) * 100) /
this.$el[this.bar.offset]
this.wrap[this.bar.scroll] =
(thumbPositionPercentage * this.wrap[this.bar.scrollSize]) /
100
},
mouseUpDocumentHandler (e) {
this.cursorDown = false
this[this.bar.axis] = 0
off(document, 'mousemove', this.mouseMoveDocumentHandler)
document.onselectstart = null
}
},
render (h) {
const { size, move, bar } = this
return (
<div
class={['ui-scrollbar__bar', 'is-' + bar.key]}
onMousedown={this.clickTrackHandler}
>
<div
ref="thumb"
class="ui-scrollbar__thumb"
onMousedown={this.clickThumbHandler}
style={renderThumbStyle({ size, move, bar })}
></div>
</div>
)
}
}
</script>

View File

@@ -0,0 +1,174 @@
<script>
import { addResizeListener, removeResizeListener, toObject } from './util'
import scrollbarWidth from './scrollbar-width'
import Bar from './bar.vue'
require('./assets/css/index.scss')
export default {
name: 'ui-scrollbar',
components: { Bar },
props: {
native: Boolean,
childOverWidth: {
type: Boolean,
default: true
},
wrapStyle: {},
wrapClass: {},
viewClass: {},
viewStyle: {},
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
tag: {
type: String,
default: 'div'
}
},
data () {
return {
sizeWidth: '0',
sizeHeight: '0',
moveX: 0,
moveY: 0,
scrollbarMiddle: 0
}
},
computed: {
wrap () {
return this.$refs.wrap
}
},
mounted () {
if (this.native) return
this.$nextTick(this.update)
!this.noresize && addResizeListener(this.$refs.resize, this.update)
!this.noresize && addResizeListener(this.$refs.wrap, this.update)
},
beforeDestroy () {
if (this.native) return
!this.noresize && removeResizeListener(this.$refs.resize, this.update)
!this.noresize && removeResizeListener(this.$refs.wrap, this.update)
},
methods: {
handleScroll () {
const wrap = this.wrap
this.moveY = (wrap.scrollTop * 100) / wrap.clientHeight
this.moveX = (wrap.scrollLeft * 100) / wrap.clientWidth
if (wrap.scrollTop + wrap.clientHeight === wrap.scrollHeight) {
this.$emit('scrollbottom')
}
if (wrap.scrollTop === 0) {
this.$emit('scrolltop')
}
this.$emit('scrollMove', {
moveX: wrap.scrollLeft,
moveY: wrap.scrollTop,
clientX: wrap.clientWidth,
clientY: wrap.clientHeight,
scrollHeight: wrap.scrollHeight,
scrollWidth: wrap.scrollWidth
})
},
update () {
let heightPercentage = null
let widthPercentage = null
const wrap = this.wrap
if (!wrap) return
heightPercentage = (wrap.clientHeight * 100) / wrap.scrollHeight
widthPercentage = (wrap.clientWidth * 100) / wrap.scrollWidth
this.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : ''
this.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : ''
},
continueScroll (rowNum) {
const wrap = this.wrap
if (this.scrollbarMiddle === 0) {
this.scrollbarMiddle = wrap.scrollTop / 2 + wrap.clientHeight / 2 - wrap.clientHeight / rowNum
}
wrap.scrollTop = this.scrollbarMiddle
}
},
render (h) {
const gutter = scrollbarWidth()
let style = this.wrapStyle
if (gutter) {
const gutterWith = `-${gutter}px`
let gutterStyle = ''
let overFlowXStr = ''
let overflowYStr = ''
if (style && style.length > 0) {
style.forEach((styleItem) => {
if (styleItem['overflow-x'] || styleItem.overflowX) {
overFlowXStr = styleItem['overflow-x'] || styleItem.overflowX
}
if (styleItem['overflow-y'] || styleItem.overflowY) {
overflowYStr = styleItem['overflow-y'] || styleItem.overflowY
}
})
}
if (overFlowXStr === 'hidden') {
gutterStyle = `margin-right: ${gutterWith};`
} else {
gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`
}
if (Array.isArray(this.wrapStyle)) {
style = toObject(this.wrapStyle)
if (overFlowXStr !== 'hidden') {
style.marginBottom = gutterWith
}
if (overflowYStr !== 'hidden') {
style.marginRight = gutterWith
}
} else if (typeof this.wrapStyle === 'string') {
style += gutterStyle
} else {
style = gutterStyle
}
}
const view = h(
this.tag,
{
class: ['ui-scrollbar__view', this.viewClass],
style: this.viewStyle,
ref: 'resize'
},
this.$slots.default
)
const wrap = (
<div
ref="wrap"
style={style}
onScroll={this.handleScroll}
class={[this.wrapClass, 'ui-scrollbar__wrap', gutter ? '' : 'ui-scrollbar__wrap--hidden-default']}
>{[view]}</div>
)
let nodes
if (!this.native) {
nodes = [
wrap,
<Bar move={this.moveX} size={this.sizeWidth}></Bar>,
<Bar vertical move={this.moveY} size={this.sizeHeight}></Bar>
]
} else {
nodes = [
<div ref="wrap" class={[this.wrapClass, 'ui-scrollbar__wrap']} style={style}>{[view]}</div>
]
}
return h('div', { class: ['ui-scrollbar', { 'child-over-width': !this.childOverWidth }] }, nodes)
}
}
</script>

View File

@@ -0,0 +1,29 @@
import Vue from 'vue'
let scrollBarWidth
export default function () {
if (Vue.prototype.$isServer) return 0
if (scrollBarWidth !== undefined) return scrollBarWidth
const outer = document.createElement('div')
outer.className = 'ui-scrollbar__wrap'
outer.style.visibility = 'hidden'
outer.style.width = '100px'
outer.style.position = 'absolute'
outer.style.top = '-9999px'
document.body.appendChild(outer)
const widthNoScroll = outer.offsetWidth
outer.style.overflow = 'scroll'
const inner = document.createElement('div')
inner.style.width = '100%'
outer.appendChild(inner)
const widthWithScroll = inner.offsetWidth
outer.parentNode.removeChild(outer)
scrollBarWidth = widthNoScroll - widthWithScroll
return scrollBarWidth
};

View File

@@ -0,0 +1,120 @@
import ResizeObserver from 'resize-observer-polyfill'
export const BAR_MAP = {
vertical: {
offset: 'offsetHeight',
scroll: 'scrollTop',
scrollSize: 'scrollHeight',
size: 'height',
key: 'vertical',
axis: 'Y',
client: 'clientY',
direction: 'top'
},
horizontal: {
offset: 'offsetWidth',
scroll: 'scrollLeft',
scrollSize: 'scrollWidth',
size: 'width',
key: 'horizontal',
axis: 'X',
client: 'clientX',
direction: 'left'
}
}
export function renderThumbStyle ({ move, size, bar }) {
const style = {}
const translate = `translate${bar.axis}(${move}%)`
style[bar.size] = size
style.transform = translate
style.msTransform = translate
style.webkitTransform = translate
return style
};
const isServer = typeof window === 'undefined'
/* istanbul ignore next */
const resizeHandler = function (entries) {
for (const entry of entries) {
const listeners = entry.target.__resizeListeners__ || []
if (listeners.length) {
listeners.forEach(fn => {
fn()
})
}
}
}
/* istanbul ignore next */
export const addResizeListener = function (element, fn) {
if (isServer) return
if (!element.__resizeListeners__) {
element.__resizeListeners__ = []
element.__ro__ = new ResizeObserver(resizeHandler)
element.__ro__.observe(element)
}
element.__resizeListeners__.push(fn)
}
/* istanbul ignore next */
export const removeResizeListener = function (element, fn) {
if (!element || !element.__resizeListeners__) return
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1)
if (!element.__resizeListeners__.length) {
element.__ro__.disconnect()
}
}
function extend (to, _from) {
for (const key in _from) {
to[key] = _from[key]
}
return to
};
export function toObject (arr) {
const res = {}
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i])
}
}
return res
};
export const on = (function () {
if (!isServer && document.addEventListener) {
return function (element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function (element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
})()
/* istanbul ignore next */
export const off = (function () {
if (!isServer && document.removeEventListener) {
return function (element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function (element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
})()

View File

@@ -0,0 +1,19 @@
// 组件
import uiJessibuca from '@/components/ui-jessibuca/index.vue'
import uiScrollbar from '@/components/ui-scrollbar/index.vue'
const components = {
// 组件
uiJessibuca,
uiScrollbar
}
const install = function (Vue, opts = {}) {
Object.keys(components).forEach((name) => {
Vue.component(name, components[name])
})
}
export default {
install
}

View File

@@ -0,0 +1,12 @@
export default {
install (Vue) {
// px 转 rem
Vue.prototype.pxTorem = (px, needUnit) => {
if (needUnit) {
return px / 19.2 + 'rem'
} else {
return px / 19.2
}
}
}
}

View File

@@ -0,0 +1,142 @@
import Vue from 'vue'
// import queryString from 'query-string'
import app from '@/views/app/index.vue'
import { router } from '@/router/index.js'
import store from '@/store/index.js'
// 请求对象
import Axios from 'axios'
// 项目本地组件全局注册
import globalComponents from './globalComponents'
// 项目本地全局方法
import globalFunctions from './globalFunctions'
// 第三方组件
// ant-design-vue 组件 按需加载
import { ConfigProvider, Input } from 'ant-design-vue'
Vue.use(globalComponents)
Vue.use(globalFunctions)
Vue.use(ConfigProvider)
Vue.use(Input)
const axiosInstance = Axios.create({
timeout: 60000
})
// 加载项目基础样式文件
require('@/assets/css/normalize.css')
// 加载项目组件覆盖样式,全局模块样式
require('@/assets/css/index.scss')
// 轮播插件swiper样式
require('swiper/css/swiper.min.css')
// 设置为 false 以阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false
process.env.VUE_APP_env === 'devmock' && require('../mock')
Vue.prototype.$axios = axiosInstance
// axios 配置 请求和响应拦截
axiosInstance.interceptors.request.use(
(config) => {
// 禁用令牌
if (
typeof config.headers.disabletoken !== 'undefined' &&
config.headers.disabletoken === true
) {
delete config.headers.disabletoken
return config
}
if (
typeof config.headers.token === 'undefined' &&
localStorage.getItem('token') !== null
) {
config.headers.token = localStorage.getItem('token')
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 异常处理
axiosInstance.interceptors.response.use(
(config) => {
if (typeof config.headers.token !== 'undefined') {
localStorage.setItem('token', config.headers.token)
}
if (
config.data &&
config.data.statusCode &&
config.data.statusCode !== '00'
) {
// 业务异常处理
let msg = 'biz error, statusCode: ' + config.data.statusCode
if (config.data.statusMsg) {
msg = msg + ', statusMsg: ' + config.data.statusMsg
}
// 打印异常信息
console.log(msg)
}
return config
},
(error) => {
// 打印异常信息
console.log(error)
if (
typeof error.response !== 'undefined' &&
error.response.status === 401
) {
console.log(error)
}
return Promise.reject(error)
}
)
// 获取必要的数据
const checkNecessaryData = (callbackFun) => {
const promiseList = []
if (promiseList.length > 0) {
Promise.all(promiseList)
.then((res) => {
localStorage.removeItem('getInitDataErrorCount')
callbackFun && callbackFun()
})
.catch((res) => {
const errorCount = localStorage.getItem(
'getInitDataErrorCount'
)
if (errorCount) {
let count = Number.parseInt(errorCount)
if (count <= 3) {
localStorage.setItem('getInitDataErrorCount', ++count)
// 菜单或者用户角色列表数据请求失败,就刷新页面
window.location.reload(window.location.href)
}
} else {
localStorage.setItem('getInitDataErrorCount', 1)
// 菜单或者用户角色列表数据请求失败,就刷新页面
window.location.reload(window.location.href)
}
})
} else {
callbackFun && callbackFun()
}
}
router.beforeEach((to, from, next) => {
checkNecessaryData(() => {
next()
})
})
new Vue({
render: (h) => h(app),
router: router,
store: store
}).$mount('#app')

View File

@@ -0,0 +1,32 @@
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const routerPush = Router.prototype.push
Router.prototype.push = function push (location) {
return routerPush.call(this, location).catch(error => error)
}
const routerList = [
{
path: '/',
component: resolve => require(['@/views/home/index.vue'], resolve),
meta: {}
}
]
const routerListMap = {}
routerList.forEach((item) => {
routerListMap[item.path] = item
})
const createRouter = () => {
return new Router({
routes: routerList
})
}
const router = createRouter()
export { router, routerListMap }

View File

@@ -0,0 +1,4 @@
const getters = {
}
export default getters

View File

@@ -0,0 +1,24 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import common from './modules/common'
import getters from './getters'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
const createPersisted = createPersistedState({
storage: window.sessionStorage,
paths: ['user']
})
const store = new Vuex.Store({
plugins: debug ? [createPersisted] : [createPersisted],
modules: {
common
},
getters
})
export default store

View File

@@ -0,0 +1,7 @@
const common = {
state: {},
mutations: {}
}
export default common

View File

@@ -0,0 +1,11 @@
import Vue from 'vue'
const user = {
state: {},
mutations: {},
actions: {}
}
export default user

View File

@@ -0,0 +1,91 @@
html,
body {
width: 100%;
height: 100%;
}
html > body {
overflow: hidden;
min-width: 1280px;
max-width: 1920px;
margin: 0 auto;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
p {
padding: 0;
margin: 0;
}
ul,
li {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
input,
button,
textarea {
outline: none;
border: none;
}
textarea {
resize: none;
}
img {
border: none;
vertical-align: middle;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.xmgl-icon {
line-height: 1;
}
.app-container {
width: 100%;
height: 100%;
background-color: #eff2f6;
.app-content{
width: 100%;
height: 100%;
}
}
.page-container {
width: 100%;
padding: p(15);
.page-title {
padding-top: p(45);
padding-bottom: p(35);
font-size: p(40);
font-weight: 700;
color: #333333;
text-align: center;
}
}
.page-content {
width: p(1200);
background-color: #ffffff;
margin: 0 auto;
box-shadow: 0 1px 0 0 rgba(178, 188, 198, 0.51);
}
.page-list-content {
background-color: #ffffff;
box-shadow: 0 1px 0 0 rgba(178, 188, 198, 0.51);
}

View File

@@ -0,0 +1,66 @@
<template>
<a-config-provider :locale="locale">
<div
class="app-container"
>
<div class="app-content" ref="app-content">
<ui-scrollbar class="app-content-scrollbar" style="height: 100%;" :childOverWidth="false" :wrapStyle="[{ overflowX: 'hidden' }]">
<router-view :style="{ 'min-height': contentMinHeight + 'px' }" :contentMinHeight=" contentMinHeight" />
</ui-scrollbar>
</div>
</div>
</a-config-provider>
</template>
<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
export default {
name: 'app',
components: {},
props: { },
data () {
return {
locale: zhCN,
contentMinHeight: 0
}
},
computed: {},
beforeCreate () {
const setHtmlFontSize = function () {
const deviceWidth =
document.documentElement.clientWidth > 1280
? document.documentElement.clientWidth <= 1920
? document.documentElement.clientWidth
: 1920
: 1280
document.getElementsByTagName('html')[0].style.cssText = 'font-size:' + deviceWidth / 100 + 'px !important'
}
let timerId
if (window.addEventListener) {
window.addEventListener(
'resize',
function () {
if (timerId) {
window.clearTimeout(timerId)
}
timerId = window.setTimeout(function () {
this.getContentMinHeight()
}, 300)
},
false
)
}
setHtmlFontSize()
},
created () {},
mounted () {
this.getContentMinHeight()
},
methods: {
getContentMinHeight () {
this.contentMinHeight = this.$refs['app-content'].clientHeight
}
}
}
</script>
<style src="./assets/css/index.scss" lang="scss"></style>

View File

@@ -0,0 +1,144 @@
.banner-comp {
width: 100%;
height: p(942);
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-pagination {
left: p(80);
width: p(15) !important;
top: 48% !important;
// overflow: initial;
.swiper-pagination-bullet {
width: p(15);
height: p(15) !important;
border-radius: p(3);
background: #1664ff !important;
opacity: 1;
}
.swiper-pagination-bullet-active-next {
transform: scale(0.33);
}
.swiper-pagination-bullet-active-prev {
transform: scale(0.33);
}
}
.hiddenPagination {
.swiper-pagination {
display: none;
}
}
.item {
width: 100%;
height: 100%;
position: relative;
.banner-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.content {
top: p(330);
left: p(216);
position: absolute;
z-index: 2;
display: flex;
flex-direction: column;
.yjqd {
letter-spacing: 3px;
color: #ffffff;
font-size: p(68);
}
.text {
font-size: p(17);
letter-spacing: 1px;
color: #d4d4d4;
}
.lxwm {
color: #ffffff;
font-size: p(16);
width: p(124);
height: p(38);
background-color: #165dff;
border-radius: 4px;
text-align: center;
line-height: p(38);
margin-top: p(33);
cursor: pointer;
}
.lxwm:hover {
background-color: #316fff;
}
.jzmd-wrap {
margin-top: p(63);
.jzmd-title {
position: relative;
line-height: 1;
padding-bottom: p(15);
margin-bottom: p(21);
font-size: p(22);
font-weight: 700;
color: #ffffff;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 2em;
height: p(2);
background-color: #aeaeb7;
border-radius: p(2);
}
}
.jzmd-content {
width: p(294);
height: p(207);
margin-left: 0;
.jzmd-row {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.jzmd-item {
display: flex;
align-items: center;
justify-content: space-between;
width: p(118);
line-height: 1;
margin-bottom: p(26);
.name {
font-size: p(16);
color: #ffffff;
}
.num-text {
display: flex;
align-items: baseline;
align-items: baseline;
.text {
font-size: p(18);
color: #ffffff;
}
.unit {
font-size: p(14);
color: #ffffff;
}
}
}
&:after {
content: '';
width: p(118);
height: 0;
}
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
.hxgn-comp{
width: 100%;
img{
height: p(639);
width: 100%;
}
}

View File

@@ -0,0 +1,163 @@
.page-home {
padding-top: p(62);
// background: url('../funasr首页3.png') center no-repeat;
// background-size: 100% 100%;
background-color: #000000;
.page-home-header{
position: fixed;
top: 0;
left: 0;
z-index: 99;
display: flex;
width: 100%;
height: p(62);
align-items: center;
border-bottom: solid 1px #202020;
background-color: #000000;
.logo-img{
width: p(110);
height: p(48);
margin-left: p(38);
margin-right: p(20);
}
ul{
display: flex;
flex: 1;
height: 100%;
align-items: center;
position: relative;
li{
color: #ffffff;
font-size: p(16);
margin-right: p(20);
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
padding: p(0) p(10);
}
li:hover{
background-color: rgb(22, 22, 22);
}
.line{
position: absolute;
background-color: #1664ff;
width: p(83);
height: p(4);
bottom: p(-1);
transition: all 0.3s;
}
}
.search-box{
display: flex;
align-items: center;
width: p(440);
height: p(62);
background-color: #292929;
border: solid 1px #464646;
transition: all 0.3s ease-out;
img{
width: p(16);
height: p(16);
margin: p(0) p(21);
}
.ant-input{
border: none;
flex: 1;
height: p(60);
background-color: #292929;
color: #fff;
font-size: p(16);
input::-webkit-input-placeholder{
color: #cccccc;
font-size: p(16);
line-height: p(60);
}
}
.ant-input:focus{
box-shadow: none !important;
}
&.search-box:hover{
background-color: #444444;
.ant-input{
background-color: #444444;
}
}
}
.language-box{
color: #ffffff;
font-size: p(16);
width: p(193);
text-align: center;
}
}
.page-home-footer{
background-color: #1b1c20;
.gywm{
display: flex;
padding: p(0) p(350);
padding-top: p(38);
img{
width: p(200);
height: p(85);
mix-blend-mode: lighten;
margin-right: p(50);
}
ul{
// flex: 1;
h3{
margin: 0;
color: #ffffff;
font-size: p(20);
margin-bottom: p(12);
}
li{
color: #999999;
font-size: p(16);
margin-bottom: p(12);
cursor: pointer;
}
li:hover{
color: #c9c9c9;
}
}
ul:nth-of-type(1){
margin-right: p(75);
}
ul:nth-of-type(2){
margin-right: p(85);
}
ul:nth-of-type(3){
margin-right: p(85);
}
ul:nth-of-type(4){
margin-right: p(95);
}
}
.line-box{
margin-top: p(50);
padding: p(0) p(350);
div{
height: 2px;
background-color: rgba(113, 113, 113, 0.5);
}
}
.ba-box{
padding: p(26) p(350) p(46);
ul{
display: flex;
justify-content: space-between;
li{
color: #fff;
color: #999999;
font-size: p(13);
}
}
}
}
}

View File

@@ -0,0 +1,195 @@
.lxwjzxfw-comp{
width: 100%;
height: p(1015);
background: url('../images/lxwjzxfw-bg.png') center no-repeat;
background-size: 100% 100%;
.lxwjzxfw-plan {
padding: p(0) p(350);
display: flex;
flex-direction: column;
}
h3 {
color: #fff;
font-size: p(22);
position: relative;
line-height: p(46);
div {
position: absolute;
bottom: 0;
left: 0;
width: p(45);
height: 2px;
background-color: #aeaeb7;
}
}
.zxfl-lc{
margin-top: p(45);
.box{
flex: 0.21;
.icon-plan{
position: relative;
}
.lc-plan{
width: p(180);
height: p(82);
background-image: linear-gradient(140deg,
#e0e4f0 0%,
#b3bad1 100%);
border-radius: 6px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
p:nth-of-type(1) {
font-size: p(20);
color: #000000;
font-weight: 600;
}
p:nth-of-type(2) {
font-size: p(16);
color: #515c73;
}
}
}
.box-5{
flex: 0.16;
}
.blue-box{
.lc-plan{
background-image: linear-gradient(0deg,
#3ebbff 0%,
#3d7df8 100%);
p{
color: #fff !important;
}
p:nth-of-type(1) {
font-size: p(20);
}
p:nth-of-type(2) {
font-size: p(16);
}
}
}
.lc-top{
display: flex;
.box-5{
.icon-plan{
.text-img{
position: absolute;
width: p(55);
height: p(61);
top: 50%;
transform: translate(0, -50%);
}
}
}
.box-3{
.lc-plan{
margin-top: p(39);
}
.icon-plan{
img{
position: absolute;
width: p(195);
height: p(138);
top: p(0);
left: p(80);
}
}
}
.box-4{
.lc-plan{
width: p(154);
height: p(70);
margin-top: p(152);
margin-left: p(15);
}
}
.icon-plan{
width: p(180);
margin: p(10) 0;
display: flex;
justify-content: center;
img{
height: p(176);
width: p(18);
}
&.xxld{
width: p(180);
background: url('../images//lxwj-xx.png') top no-repeat;
background-size: 100% p(127);
}
}
}
.lc-bottom{
display: flex;
.box{
display: flex;
align-items: center;
}
.icon-plan{
flex: 1;
display: flex;
img{
margin: auto;
width: p(57);
height: p(18);
}
}
}
.lxwj-text{
color: #ffffff;
font-size: p(18);
margin-top: p(40);
}
}
.xq-box{
display: flex;
align-items: flex-end;
.video-box{
width: p(517);
height: p(290);
// background-color: #165dff;
margin-right: p(188);
iframe{
width: 100%;
height: 100%;
}
}
.btn-box{
margin-top: p(80);
li{
width: p(190);
height: p(55);
background-color: #165dff;
border-radius: p(4);
display: flex;
align-items: center;
justify-content: space-evenly;
margin-bottom: p(40);
cursor: pointer;
img{
width: p(26);
}
p{
color: #ffffff;
font-size: p(24);
}
}
li:last-child {
margin-bottom: p(15);
}
li:hover{
background-color: #3f77fc;
}
}
}
}

View File

@@ -0,0 +1,34 @@
.mxjs-comp {
background: url('../images/mxjs-bg.png') center no-repeat;
background-size: 100% 100%;
.mxjs-plan {
padding: p(0) p(350);
display: flex;
flex-direction: column;
}
h3 {
color: #24242f;
font-size: p(22);
position: relative;
line-height: p(46);
div {
position: absolute;
bottom: 0;
left: 0;
width: p(45);
height: 2px;
background-color: #aeaeb7;
}
}
img {
width: p(888);
height: p(613);
margin: auto;
}
p {
color: #333333;
font-size: p(18);
margin-top: p(10);
padding-bottom: p(83);
}
}

View File

@@ -0,0 +1,312 @@
.sstx-comp{
width: 100%;
height: p(1100);
background: url('../images/sstx-bg.png') center no-repeat;
background-size: 100% 100%;
.lxwjzxfw-plan{
padding: p(0) p(350);
display: flex;
flex-direction: column;
}
.sstx-plan{
// padding: p(0) p(350);
display: flex;
flex-direction: column;
}
h3 {
color: #fff;
font-size: p(22);
position: relative;
line-height: p(46);
div {
position: absolute;
bottom: 0;
left: 0;
width: p(45);
height: 2px;
background-color: #aeaeb7;
}
}
.sstx-lc{
padding-top: p(36);
.box{
flex: 1;
display: flex;
justify-content: center;
position: relative;
.lc-plan{
width: p(250);
height: p(84);
background-image: linear-gradient(140deg,
#e0e4f0 0%,
#b3bad1 100%);
border-radius: 6px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
p:nth-of-type(1) {
font-size: p(20);
color: #000000;
font-weight: 600;
}
p:nth-of-type(2) {
font-size: p(16);
color: #515c73;
}
}
.icon-plan{
}
}
.box-min{
.lc-plan{
width: p(180);
height: p(70);
}
}
.blue-box{
.lc-plan{
background-image: linear-gradient(140deg,
rgba(22, 92, 255, 0.3) 0%,
rgba(22, 92, 255, 0.3) 100%);
border-radius: 6px;
border: dashed 2px rgba(22, 92, 255, 0.8);
p{
color: #fff !important;
}
p:nth-of-type(1) {
font-size: p(20);
}
p:nth-of-type(2) {
font-size: p(16);
}
}
}
.lc-top{
display: flex;
.lc-plan{
}
.icon-plan{
}
.box-1{
.icon-plan{
position: absolute;
bottom: p(-48);
img{
width: p(18);
}
p{
position: absolute;
font-size: p(18);
color: #fff;
top: 10%;
right: 50%;
transform: translate(60%, 0);
width: max-content;
letter-spacing: p(15);
}
}
}
}
.lc-center{
display: flex;
align-items: center;
height: p(115);
background-color: rgba(179, 186, 209, 0.25);
border-radius: 4px;
border: solid 1px rgba(179, 186, 209, 0.8);
margin-top: p(30);
margin-bottom: p(20);
.box-1,.box-2{
.icon-plan,.icon-plan1{
position: absolute;
// bottom: p(-48);
right: p(-60);
top: 50%;
transform: translate(0, -50%);
img{
width: p(140);
height: p(18);
}
div{
position: absolute;
top: p(-12);
width: p(140);
p{
font-size: p(18);
color: #fff;
text-align: center;
}
}
}
}
.box-2{
.icon-plan1{
right: p(-200);
img{
width: p(286);
}
div{
width: p(286);
}
}
.icon-plan2{
position: absolute;
bottom: p(-80);
img{
width: p(18);
height: p(90);
}
p{
position: absolute;
font-size: p(18);
color: #fff;
top: 60%;
right: 50%;
transform: translate(50%, 0);
width: max-content;
}
}
}
}
.lc-bottom{
display: flex;
align-items: center;
padding-top: p(20);
height: p(160);
background-color: rgba(179, 186, 209, 0.25);
border-radius: 4px;
border: solid 1px rgba(179, 186, 209, 0.8);
.box-1{
.icon-plan1{
position: absolute;
top: p(-90);
img{
width: p(18);
height: p(90);
}
p{
position: absolute;
font-size: p(18);
color: #fff;
top: 60%;
right: 50%;
transform: translate(50%, 0);
width: max-content;
}
}
.icon-plan2{
position: absolute;
right: p(-65);
top: 50%;
transform: translate(0, -50%);
img{
width: p(140);
height: p(18);
}
div{
position: absolute;
top: p(-12);
width: p(140);
p{
font-size: p(18);
color: #fff;
text-align: center;
}
}
}
}
.box-2{
.icon-plan{
position: absolute;
right: p(-30);
top: 50%;
transform: translate(0, -50%);
img{
width: p(140);
height: p(18);
}
}
}
.box-3{
.icon-plan{
position: absolute;
top: p(-210);
img{
width: p(18);
height: p(210);
}
p{
position: absolute;
font-size: p(18);
color: #fff;
bottom: 2%;
right: 50%;
transform: translate(65%, 0);
width: max-content;
}
}
}
}
.lxwj-text{
color: #ffffff;
font-size: p(18);
margin-top: p(45);
}
}
.xq-box{
display: flex;
align-items: flex-end;
.video-box{
width: p(517);
height: p(290);
// background-color: #165dff;
margin-right: p(188);
iframe{
width: 100%;
height: 100%;
}
}
.btn-box{
margin-top: p(80);
li{
width: p(190);
height: p(55);
background-color: #165dff;
border-radius: p(4);
display: flex;
align-items: center;
justify-content: space-evenly;
margin-bottom: p(40);
cursor: pointer;
img{
width: p(26);
}
p{
color: #ffffff;
font-size: p(24);
}
}
li:last-child {
margin-bottom: p(15);
}
li:hover{
background-color: #3f77fc;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

View File

@@ -0,0 +1,171 @@
<template>
<div class="banner-comp">
<div
class="swiper-container"
ref="swiper-container"
:class="{ hiddenPagination: bannerList && bannerList.length < 2 }"
>
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(item, index) in bannerList" :key="index">
<div class="item">
<img class="banner-bg" :src="item.url" alt />
<div v-if="item.flag === 1" class="content">
<h3 class="yjqd">一键启动FUNASR</h3>
<p class="text">
FUNASR希望在语音识别的学术研究和工业应用之间架起一座桥梁通过发布工业级
<br />语音识别模型的训练和微调研究人员和开发人员可以更方便地进行语音识别模型的
<br />研究和生产并推动语音识别生态的发展让语音识别更有趣
</p>
<div class="lxwm">联系我们</div>
<div class="jzmd-wrap">
<div class="jzmd-title">捐赠名单</div>
<div class="jzmd-content swiper-container" ref="jzmd-swiper">
<div class="swiper-wrapper">
<div
class="jzmd-row swiper-slide"
v-for="(item,index) in jzmdRows"
:key="index"
>
<div class="jzmd-item" v-if="jzmdList[2 * (item -1)]">
<div class="name">{{ jzmdList[2 * (item -1)].name }}</div>
<div class="num-text">
<span class="text">{{ jzmdList[2 * (item -1)].num }}</span>
<span class="unit"></span>
</div>
</div>
<div class="jzmd-item" v-if="jzmdList[2 * (item -1) + 1]">
<div class="name">{{ jzmdList[2 * (item -1) + 1].name }}</div>
<div class="num-text">
<span class="text">{{ jzmdList[2 * (item -1) + 1].num }}</span>
<span class="unit"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</template>
<script>
import Swiper from 'swiper'
export default {
name: 'banner-comp',
data () {
return {
bannerList: [
{
flag: 1,
url: require('./assets/images/banner.png')
}
],
swiperObj: null,
jzmdSwiperObj: null,
jzmdList: [
{
name: '刘连响',
num: 300
},
{
name: '程俊陶',
num: 300
},
{
name: '黄明',
num: 236
},
{
name: '高志付',
num: 235
},
{
name: '陈翔',
num: 200
},
{
name: '夏侯杰',
num: 200
},
{
name: '黄药师',
num: 198
},
{
name: '肖炜',
num: 100
},
{
name: '刘柱',
num: 100
},
{
name: '黄水杯',
num: 85
},
{
name: '子龙',
num: 85
}
]
}
},
computed: {
jzmdRows () {
return Math.ceil(this.jzmdList.length / 2)
}
},
mounted () {
this.$nextTick(() => {
this.initSwiper()
})
this.initJzmdSwiper()
},
methods: {
initSwiper () {
if (this.swiperObj) {
this.swiperObj.destroy()
}
// const that = this
this.swiperObj = new Swiper(this.$refs['swiper-container'], {
slidesPerView: 1,
direction: 'vertical',
pagination: {
el: '.swiper-pagination',
dynamicBullets: true
},
on: {
slideChangeTransitionEnd: function () {},
init: function () {}
}
})
},
initJzmdSwiper () {
if (this.jzmdSwiperObj) {
this.jzmdSwiperObj.destroy()
}
// const that = this
this.jzmdSwiperObj = new Swiper(this.$refs['jzmd-swiper'], {
direction: 'vertical',
autoplay: {
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: false
},
slidesPerView: 5,
slidesPerGroup: 1,
loop: true,
loopedSlides: 7
})
}
}
}
</script>
<style src="./assets/css/banner.scss" lang="scss"></style>

View File

@@ -0,0 +1,16 @@
<template>
<div class="hxgn-comp">
<img src="./assets/images/hxgn.png" alt="">
</div>
</template>
<script>
export default {
name: 'hxgn-comp',
data () {
return {
}
},
methods: {}
}
</script>
<style src="./assets/css/hxgn.scss" lang="scss"></style>

View File

@@ -0,0 +1,288 @@
<template>
<div class="page page-home">
<header class="page-home-header">
<img class="logo-img" src="./assets/images/logo.png" alt="">
<ul>
<li :ref="item.ref" v-for="(item, index) in headerList" :key="index" @click="anchorTo(item)">
<p>{{item.name}}</p>
</li>
<li @click="toPage({link: 'https://github.com/alibaba-damo-academy/FunASR'})">
Github
</li>
<li>
社区交流
</li>
<div :style="{width: lineWidth + 'px', left: lineLeft + 'px'}" class="line"></div>
</ul>
<div class="search-box">
<img src="./assets/images/ss.png" alt="">
<a-input placeholder="请输入关键字" />
</div>
<div class="language-box">
中文/EN
</div>
</header>
<banner-comp ref="funasrJs" />
<hxgn-comp ref="hxgn" />
<mxjs-comp ref="mxjs" />
<lxwjzxfw-comp ref="lxwj" />
<sstx-comp ref="sstx" />
<footer class="page-home-footer">
<div class="gywm">
<img src="./assets/images/footer-logo.png" alt="">
<ul v-for="(item, index) in footerList" :key="index">
<h3>{{item.title}}</h3>
<li @click="toPage(cItem)" v-for="(cItem, cIndex) in item.childer" :key="cIndex">
{{cItem.name}}
</li>
</ul>
</div>
</footer>
</div>
</template>
<script>
import bannerComp from './banner.vue'
import hxgnComp from './hxgn.vue'
import mxjsComp from './mxjs.vue'
import lxwjzxfwComp from './lxwjzxfw.vue'
import sstxComp from './sstx.vue'
export default {
name: 'page-home',
components: {
bannerComp,
hxgnComp,
mxjsComp,
lxwjzxfwComp,
sstxComp
},
data () {
return {
headerList: [
{
name: 'funasr介绍',
ref: 'h-funasrJs',
isAnchor: true
},
{
name: '核心功能',
ref: 'h-hxgn',
isAnchor: true
},
{
name: 'Paraformer模型介绍',
ref: 'h-mxjs',
isAnchor: true
},
{
name: '离线文件转写服务',
ref: 'h-lxwj',
isAnchor: true
},
{
name: '实时听写',
ref: 'h-sstx',
isAnchor: true
}
// {
// name: 'Github',
// ref: 'h-github'
// },
// {
// name: '社区交流',
// ref: 'h-sqjl'
// }
],
footerList: [
{
title: 'Funasr介绍',
childer: [
{
name: '关于我们',
link: ''
}
]
},
{
title: '核心功能',
childer: [
{
name: '核心介绍',
link: ''
}
]
},
{
title: 'Paraformer模型介绍',
childer: [
{
name: '模型结构固',
link: ''
},
{
name: '模型介绍',
link: ''
}
]
},
{
title: '离线文件转写服务',
childer: [
{
name: '原理图',
link: ''
},
{
name: '文字介绍',
link: ''
},
{
name: '安装',
link: ''
},
{
name: '使用',
link: ''
},
{
name: '视频教程链接',
link: ''
}
]
},
{
title: '实时听写',
childer: [
{
name: '原理图',
link: ''
},
{
name: '文字介绍',
link: ''
},
{
name: '安装',
link: ''
},
{
name: '使用',
link: ''
},
{
name: '视频教程链接',
link: ''
}
]
}
],
headerActive: 'h-funasrJs',
lineWidth: 0,
lineLeft: 0
}
},
created () {},
mounted () {
this.$nextTick(() => {
this.getLineWidth()
this.handlerNodeScroll()
this.getAnchorDetails()
})
},
methods: {
// 底部跳转
toPage (item) {
if (item.link) window.open(item.link)
},
// 获取元素的高度,距离顶部距离
getAnchorDetails () {
for (let i = 0; i < this.headerList.length; i++) {
const item = this.headerList[i]
if (item.isAnchor) {
const refName = item.ref.split('-')[1]
const dom = this.$refs[refName].$el
item.height = dom.offsetHeight
item.top = dom.offsetTop
}
}
},
// 头部锚点按钮
anchorTo (item) {
this.headerActive = item.ref
this.getLineWidth()
if (item.isAnchor) {
const refName = item.ref.split('-')[1]
this.scrollToFn(refName)
}
},
// 设置滚动距离
scrollToFn (refName) {
const dom = this.$refs[refName].$el
const top = dom.offsetTop
const appContentScrollbar = document.getElementsByClassName('app-content-scrollbar')[0]
const uiModalWrap = appContentScrollbar.getElementsByClassName('ui-scrollbar__wrap')[0]
uiModalWrap.scrollTo({
top: top - 70,
left: 0,
behavior: 'smooth'
})
},
// 获取头部选中样式
getLineWidth () {
const dom = this.$refs[this.headerActive][0]
if (!dom) return
this.lineWidth = dom.offsetWidth
this.lineLeft = dom.offsetLeft
},
// 监听元素滚动
handlerNodeScroll () {
const self = this
// 函数防抖
const fun = self.debounce(e => {
// 距顶部
const scrollTop = e.target.scrollTop
let toActive = null
for (let i = 0; i < self.headerList.length; i++) {
const item = self.headerList[i]
if (scrollTop > (item.top - 90)) {
toActive = item
}
}
if (toActive && toActive.top) {
self.headerActive = toActive.ref
self.getLineWidth()
}
}, 100)
// 监听滚动
const appContentScrollbar = document.getElementsByClassName('app-content-scrollbar')[0]
const uiModalWrap = appContentScrollbar.getElementsByClassName('ui-scrollbar__wrap')[0]
uiModalWrap.addEventListener('scroll', function (e) {
fun(e)
})
},
// 函数防抖
debounce (handle, delay) {
let timer = null
return function () {
const _self = this
const _args = arguments
clearTimeout(timer)
timer = setTimeout(function () {
handle.apply(_self, _args)
}, delay)
}
}
}
}
</script>
<style src="./assets/css/index.scss" lang="scss"></style>

View File

@@ -0,0 +1,157 @@
<template>
<div class="lxwjzxfw-comp">
<div class="lxwjzxfw-plan">
<h3>
离线文件转写服务
<div></div>
</h3>
<div class="zxfl-lc">
<div class="lc-top">
<div class="box box-1">
<div class="lc-plan">
<p>消息队列</p>
<p>(从客户端接收)</p>
</div>
<div class="icon-plan xxld">
<img src="./assets/images/lxwj-to-bottom.png" alt="">
</div>
</div>
<div class="box box-2">
</div>
<div class="box box-3 blue-box">
<div class="lc-plan">
<p>语言模型</p>
<p>Ngram/Token/Lex</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-yymx.png" alt="">
</div>
</div>
<div class="box box-4 blue-box">
<div class="lc-plan">
<p>消息队列</p>
<p>(从客户端接收)</p>
</div>
</div>
<div class="box box-5">
<div class="lc-plan">
<p>消息队列</p>
<p>(从客户端接收)</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-to-top.png" alt="">
<img class="text-img" src="./assets/images/lxwj-text.png" alt="">
</div>
</div>
</div>
<div class="lc-bottom">
<div class="box box-1">
<div class="lc-plan">
<p>语音端点检测</p>
<p>FSMN-VAD</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-to-right.png" alt="">
</div>
</div>
<div class="box box-2">
<div class="lc-plan">
<p>声学模型</p>
<p>Paraformer</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-to-right.png" alt="">
</div>
</div>
<div class="box box-3 blue-box">
<div class="lc-plan">
<p>解码器</p>
<p>Wfst decoder</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-to-right.png" alt="">
</div>
</div>
<div class="box box-4">
<div class="lc-plan">
<p>标点预测</p>
<p>CT-Transformer</p>
</div>
<div class="icon-plan">
<img src="./assets/images/lxwj-to-right.png" alt="">
</div>
</div>
<div class="box box-5">
<div class="lc-plan">
<p>逆文本正则化</p>
<p>ITN</p>
</div>
</div>
</div>
<p class="lxwj-text">
FunASR离线文件转写软件包提供了一款功能强大的语音离线文件转写服务拥有完整的语音识别链路结合了语音端点检测语音识别标点等模型可以将几十个小时的长音频与视频识别成带标点的文字而且支持上百路请求同时进行转写输出为带标点的文字含有字级别时间戳支持ITN与用户自定义热词等服务端集成有ffmpeg支持各种音视频格式输入软件包提供有htmlpythonc++java与c#等多种编程语言客户端用户可以直接使用与进一步开发
</p>
</div>
<div class="xq-box">
<div class="video-box">
<iframe src="//player.bilibili.com/player.html?aid=663707374&bvid=BV11a4y1U72y&cid=1338069747&p=1&autoplay=0" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="false"> </iframe>
<!-- <LivePlayer
:autoplay="false"
:videoUrl="videoSrc"
></LivePlayer> -->
</div>
<div class="btn-box">
<li v-for="(item, index) in btnList" :key="index" @click="toPage(item)">
<img :src="item.icon" alt="">
<p>{{item.title}}</p>
</li>
</div>
</div>
</div>
</div>
</template>
<script>
// import LivePlayer from '@liveqing/liveplayer'
export default {
name: 'lxwjzxfw-comp',
// components: {
// LivePlayer
// },
data () {
return {
btnList: [
{
icon: require('./assets/images/lxwj-zxty.png'),
title: '在线体验',
link: 'https://www.funasr.com/static/offline/index.html'
},
{
icon: require('./assets/images/lxwj-az.png'),
title: '安 装',
link: 'https://github.com/alibaba-damo-academy/FunASR/blob/main/runtime/docs/SDK_advanced_guide_offline_zh.md'
},
{
icon: require('./assets/images/lxwj-sy.png'),
title: '使 用',
link: 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/sample/funasr_samples.tar.gz'
}
],
videoSrc: 'https://www.bilibili.com/video/BV11a4y1U72y/?share_source=copy_web&vd_source=f6576748261a1b738a71ad618d380438'
// videoSrc: 'https://www.bilibili.com/video/BV11a4y1U72y/?share_source=copy_web&vd_source=f6576748261a1b738a71ad618d380438'
}
},
methods: {
toPage (item) {
if (item.link) window.open(item.link)
}
}
}
</script>
<style src="./assets/css/lxwjzxfw.scss" lang="scss"></style>

View File

@@ -0,0 +1,25 @@
<template>
<div class="mxjs-comp">
<div class="mxjs-plan">
<h3>
Paraformer模型介绍
<div></div>
</h3>
<img src="./assets/images/mxjs.png" alt="">
<p>
Paraformer是一种非自回归端到端语音识别模型非自回归模型相比于目前主流的自回归模型可以并行的对整条句子输出目标文字特别适合利用GPU进行并行推理Paraformer是目前已知的首个在工业大数据上可以获得和自回归端到端模型相同性能的非自回归模型配合GPU推理可以将推理效率提升10倍从而将语音识别云服务的机器成本降低接近10倍
</p>
</div>
</div>
</template>
<script>
export default {
name: 'mxjs-comp',
data () {
return {
}
},
methods: {}
}
</script>
<style src="./assets/css/mxjs.scss" lang="scss"></style>

View File

@@ -0,0 +1,174 @@
<template>
<div class="sstx-comp">
<div class="lxwjzxfw-plan">
<div class="sstx-plan">
<h3>
实时听写
<div></div>
</h3>
</div>
<div class="sstx-lc">
<div class="lc-top">
<div class="box box-1 box-min">
<div class="lc-plan">
<p>消息队列</p>
<p>(从客户端接收)</p>
</div>
<div class="icon-plan">
<img src="./assets/images/sstx-yp.png" alt="">
<p>音频</p>
</div>
</div>
<div class="box box-2">
</div>
<div class="box box-3 box-min">
<div class="lc-plan">
<p>消息队列</p>
<p>(发送到客户端)</p>
</div>
<div class="icon-plan">
</div>
</div>
</div>
<div class="lc-center">
<div class="box box-1">
<div class="lc-plan">
<p>FSMN-VAD-realtime</p>
<p>(端点检测实时)</p>
</div>
<div class="icon-plan">
<img src="./assets/images/sstx-fjyd.png" alt="">
<div>
<p>非静音段</p>
<p>间隔600ms</p>
</div>
</div>
</div>
<div class="box box-2">
<div class="lc-plan">
<p>Paraformmer-online</p>
<p>(语音识别实时)</p>
</div>
<div class="icon-plan1">
<img src="./assets/images/sstx-sbwz-max.png" alt="">
<div>
<p>识别文字</p>
<p>间隔600ms</p>
</div>
</div>
<div class="icon-plan2">
<img src="./assets/images/sstx-vad.png" alt="">
<p>VAD&nbsp;&nbsp;&nbsp;&nbsp;尾点</p>
</div>
</div>
<div class="box box-3">
</div>
</div>
<div class="lc-bottom">
<div class="box box-1 blue-box">
<div class="lc-plan">
<p>FSMN-VAD-realtime</p>
<p>(语音识别非实时)</p>
</div>
<div class="icon-plan1">
<img src="./assets/images/sstx-vad.png" alt="">
<p>VAD&nbsp;&nbsp;&nbsp;&nbsp;尾点</p>
</div>
<div class="icon-plan2">
<img src="./assets/images/sstx-sbwz.png" alt="">
<div>
<p>识别文字</p>
</div>
</div>
</div>
<div class="box box-2">
<div class="lc-plan">
<p>CT-Transformer</p>
<p>(标点预测)</p>
</div>
<div class="icon-plan">
<div class="icon-plan">
<img src="./assets/images/sstx-fjyd.png" alt="">
</div>
</div>
</div>
<div class="box box-3">
<div class="lc-plan">
<p>ITN</p>
<p>(逆文本正则化)</p>
</div>
<div class="icon-plan">
<img src="./assets/images/sstx-xz.png" alt="">
<div>
<p>修正&nbsp;&nbsp;&nbsp;识别文字</p>
</div>
</div>
</div>
</div>
<p class="lxwj-text">
FunASR实时语音听写软件包集成了实时版本的语音端点检测模型语音识别语音识别标点预测模型等采用多模型协同既可以实时的进行语音转文字也可以在说话句尾用高精度转写文字修正输出输出文字带有标点支持多路请求依据使用者场景不同支持实时语音听写服务online非实时一句话转写offline与实时与非实时一体化协同2pass3种服务模式软件包提供有htmlpythonc++java与c#等多种编程语言客户端用户可以直接使用与进一步开发
</p>
</div>
<div class="xq-box">
<div class="video-box">
<iframe src="//player.bilibili.com/player.html?aid=278639821&bvid=BV1Yw411K7LY&cid=1338073559&p=1&autoplay=0" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" > </iframe>
<!-- <LivePlayer
:autoplay="false"
:videoUrl="videoSrc"
></LivePlayer> -->
</div>
<div class="btn-box">
<li v-for="(item, index) in btnList" :key="index" @click="toPage(item)">
<img :src="item.icon" alt="">
<p>{{item.title}}</p>
</li>
</div>
</div>
</div>
</div>
</template>
<script>
// import LivePlayer from '@liveqing/liveplayer'
export default {
name: 'sstx-comp',
// components: {
// LivePlayer
// },
data () {
return {
btnList: [
{
icon: require('./assets/images/lxwj-zxty.png'),
title: '在线体验',
link: 'https://www.funasr.com/static/online/index.html'
},
{
icon: require('./assets/images/lxwj-az.png'),
title: '安 装',
link: 'https://github.com/alibaba-damo-academy/FunASR/blob/main/runtime/docs/SDK_advanced_guide_online_zh.md'
},
{
icon: require('./assets/images/lxwj-sy.png'),
title: '使 用',
link: 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/sample/funasr_samples.tar.gz'
}
],
videoSrc: 'https://www.bilibili.com/video/BV1Yw411K7LY/?share_source=copy_web&vd_source=f6576748261a1b738a71ad618d380438'
}
},
methods: {
toPage (item) {
if (item.link) window.open(item.link)
}
}
}
</script>
<style src="./assets/css/sstx.scss" lang="scss"></style>