Add wvpjar as git submodule

- Added wvpjar submodule pointing to a-wvp-java.git
- Updated .gitmodules configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
孙小云 2026-01-13 18:35:56 +08:00
parent 968f62c7e8
commit cd53305852
321 changed files with 61715 additions and 0 deletions

3
.gitmodules vendored
View File

@ -43,3 +43,6 @@
[submodule "a_th_web"] [submodule "a_th_web"]
path = a_th_web path = a_th_web
url = http://th.local.t-aaron.com:13000/THENG/a_th_web.git url = http://th.local.t-aaron.com:13000/THENG/a_th_web.git
[submodule "wvpjar"]
path = wvpjar
url = http://th.local.t-aaron.com:13000/THENG/a-wvp-java.git

1
wvpjar Submodule

@ -0,0 +1 @@
Subproject commit 3fdfd28dcd21ec24fb59d0f11ce9f7ccf7db520e

14
wvpweb/.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

5
wvpweb/.env.development Normal file
View File

@ -0,0 +1,5 @@
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'

6
wvpweb/.env.production Normal file
View File

@ -0,0 +1,6 @@
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = ''

8
wvpweb/.env.staging Normal file
View File

@ -0,0 +1,8 @@
NODE_ENV = production
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'

4
wvpweb/.eslintignore Normal file
View File

@ -0,0 +1,4 @@
build/*.js
src/assets
public
dist

48
wvpweb/.eslintrc.js Normal file
View File

@ -0,0 +1,48 @@
module.exports = {
root: true,
env: {
node: true,
browser: true,
},
extends: ["plugin:vue/essential", "eslint:recommended"],
parserOptions: {
parser: "babel-eslint",
},
rules: {
// Disable or downgrade problematic rules
"vue/require-prop-types": "off",
"vue/require-default-prop": "off",
"vue/no-unused-vars": "warn",
"no-unused-vars": "warn",
"no-undef": "warn",
eqeqeq: "warn",
"no-return-assign": "warn",
"new-cap": "warn",
"vue/html-self-closing": "off",
"vue/html-closing-bracket-spacing": "off",
"vue/this-in-template": "off",
"vue/require-v-for-key": "warn",
"vue/valid-v-model": "warn",
"vue/attributes-order": "off",
"no-multiple-empty-lines": "warn",
// Style rules - make them warnings instead of errors
quotes: ["warn", "single"],
"comma-dangle": ["warn", "never"],
"space-in-parens": "warn",
"comma-spacing": "warn",
"object-curly-spacing": ["warn", "always"],
"arrow-spacing": "warn",
semi: ["warn", "never"],
"no-multi-spaces": "warn",
// Turn off console warnings for development
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
},
globals: {
// Define global variables to prevent 'undefined' errors
ZLMRTCClient: "readonly",
jessibuca: "readonly",
},
}

16
wvpweb/.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
tests/**/coverage/
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

5
wvpweb/.travis.yml Normal file
View File

@ -0,0 +1,5 @@
language: node_js
node_js: 10
script: npm run test
notifications:
email: false

21
wvpweb/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017-present PanJiaChen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

111
wvpweb/README-zh.md Normal file
View File

@ -0,0 +1,111 @@
# vue-admin-template
> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint这些搭建后台必要的东西。
[线上地址](http://panjiachen.github.io/vue-admin-template)
[国内访问](https://panjiachen.gitee.io/vue-admin-template)
目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Extra
如果你想要根据用户角色来动态生成侧边栏和 router你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
## 相关项目
- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
## Build Setup
```bash
# 克隆项目
git clone https://github.com/PanJiaChen/vue-admin-template.git
# 进入项目目录
cd vue-admin-template
# 安装依赖
npm install
# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev
```
浏览器访问 [http://localhost:9528](http://localhost:9528)
## 发布
```bash
# 构建测试环境
npm run build:stage
# 构建生产环境
npm run build:prod
```
## 其它
```bash
# 预览发布环境效果
npm run preview
# 预览发布环境效果 + 静态资源分析
npm run preview -- --report
# 代码格式检查
npm run lint
# 代码格式检查并自动修复
npm run lint -- --fix
```
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
## 购买贴纸
你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。
## Demo
![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
Copyright (c) 2017-present PanJiaChen

99
wvpweb/README.md Normal file
View File

@ -0,0 +1,99 @@
# vue-admin-template
English | [简体中文](./README-zh.md)
> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
**Live demo:** http://panjiachen.github.io/vue-admin-template
**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Build Setup
```bash
# clone the project
git clone https://github.com/PanJiaChen/vue-admin-template.git
# enter the project directory
cd vue-admin-template
# install dependency
npm install
# develop
npm run dev
```
This will automatically open http://localhost:9528
## Build
```bash
# build for test environment
npm run build:stage
# build for production environment
npm run build:prod
```
## Advanced
```bash
# preview the release environment effect
npm run preview
# preview the release environment effect + static resource analysis
npm run preview -- --report
# code format check
npm run lint
# code format check and auto fix
npm run lint -- --fix
```
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
## Demo
![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
## Extra
If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
## Related Project
- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
Copyright (c) 2017-present PanJiaChen

14
wvpweb/babel.config.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
presets: [
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
'@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
'plugins': ['dynamic-import-node']
}
}
}

24
wvpweb/jest.config.js Normal file
View File

@ -0,0 +1,24 @@
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
coverageDirectory: '<rootDir>/tests/unit/coverage',
// 'collectCoverage': true,
'coverageReporters': [
'lcov',
'text-summary'
],
testURL: 'http://localhost/'
}

9
wvpweb/jsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

78
wvpweb/package.json Normal file
View File

@ -0,0 +1,78 @@
{
"name": "vue-admin-template",
"version": "4.4.0",
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>",
"scripts": {
"dev": "vue-cli-service serve --host=0.0.0.0",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit"
},
"dependencies": {
"@femessage/log-viewer": "^1.5.0",
"@wchbrad/vue-easy-tree": "^1.0.13",
"axios": "^0.24.0",
"core-js": "3.6.5",
"dayjs": "^1.11.13",
"echarts": "^4.9.0",
"element-ui": "^2.15.14",
"gcoord": "^1.0.7",
"js-cookie": "2.2.0",
"moment": "^2.29.1",
"moment-duration-format": "^2.3.2",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"ol": "^10.6.1",
"path-to-regexp": "2.4.0",
"screenfull": "5.1.0",
"strip-ansi": "^7.1.0",
"v-charts": "^1.19.0",
"vue": "2.6.10",
"vue-clipboard2": "^0.3.3",
"vue-clipboards": "^1.3.0",
"vue-contextmenujs": "^1.4.11",
"vue-router": "3.0.6",
"vue-ztree-2.0": "^1.0.4",
"vuex": "3.1.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.4",
"@vue/cli-plugin-eslint": "4.4.4",
"@vue/cli-plugin-unit-jest": "4.4.4",
"@vue/cli-service": "4.4.4",
"@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "9.5.1",
"babel-eslint": "10.1.0",
"babel-jest": "23.6.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "2.4.2",
"connect": "3.6.6",
"eslint": "6.7.2",
"eslint-plugin-vue": "6.2.2",
"html-webpack-plugin": "3.2.0",
"mockjs": "1.0.1-beta3",
"runjs": "4.3.2",
"sass": "1.26.8",
"sass-loader": "8.0.2",
"script-ext-html-webpack-plugin": "2.1.3",
"serve-static": "1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"vue-template-compiler": "2.6.10"
},
"browserslist": [
"> 1%",
"last 2 versions"
],
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
},
"license": "MIT"
}

8
wvpweb/postcss.config.js Normal file
View File

@ -0,0 +1,8 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
'plugins': {
// to edit target browsers: use "browserslist" field in package.json
'autoprefixer': {}
}
}

BIN
wvpweb/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

22
wvpweb/public/index.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title>
</head>
<body>
<script type="text/javascript" src="./static/js/jessibuca/jessibuca.js"></script>
<script type="text/javascript" src="./static/js/ZLMRTCClient.js"></script>
<script type="text/javascript" src="./static/js/config.js"></script>
<script type="text/javascript" src="./static/js/h265web/h265webjs-v20221106.js"></script>
<script type="text/javascript" src="./static/js/h265web/missile.js"></script>
<noscript>
<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
window.baseUrl = ""
// map组件全局参数, 注释此内容可以关闭地图功能
window.mapParam = {
// 开启/关闭地图功能
enable: true,
// 坐标系 GCJ02 WGS84,
coordinateSystem: "GCJ02",
// 地图瓦片地址
tilesUrl: "http://webrd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
// 瓦片大小
tileSize: 256,
// 默认层级
zoom:10,
// 默认地图中心点
center:[116.41020, 39.915119],
// 地图最大层级
maxZoom:18,
// 地图最小层级
minZoom: 3
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,97 @@
export interface Web265JsExtraConfig {
moovStartFlag?: boolean
rawFps?: number
autoCrop?: boolean
core?: 0 | 1
coreProbePart?: number
ignoreAudio?: 0 | 1
probeSize?: number
}
export interface Web265JsConfig {
/**
*The type of the file to be played, do not fill in the automatic identification
*/
type?: 'mp4' | 'hls' | 'ts' | 'raw265' | 'flv'
/**
* playback window dom id value
*/
player: string
/**
* the video window width size
*/
width: number
/**
* the video window height size
*/
height: number
/**
* player token value
*/
token: string
extInfo?: Web265JsExtraConfig
}
export interface Web265JsMediaInfo {
audioNone: boolean
durationMs: number
fps: number
sampleRate: number
size: {
height: number
width: number
}
videoCodec: 0 | 1
isHEVC: boolean
videoType: Web265JsConfig['type']
}
interface New265WebJs {
onSeekFinish(): void
onRender(
width: number,
height: number,
imageBufferY: typeof Uint8Array,
imageBufferB: typeof Uint8Array,
imageBufferR: typeof Uint8Array
): void
onLoadFinish(): void
onPlayTime(videoPTS: number): void
onPlayFinish(): void
onCacheProcess(cPts: number): void
onReadyShowDone(): void
onLoadCache(): void
onLoadCacheFinshed(): void
onOpenFullScreen(): void
onCloseFullScreen(): void
do(): void
pause(): void
isPlaying(): boolean
setRenderScreen(state: boolean): void
seek(pts: number): void
setVoice(volume: number): void
mediaInfo(): Web265JsMediaInfo
fullScreen(): void
closeFullScreen(): void
playNextFrame(): void
snapshot(): void
release(): void
setPlaybackRate(rate: number): void
getPlaybackRate(): number
}
declare type new265webJsFn = (
url: string,
config: Web265JsConfig
) => New265WebJs
declare global {
interface Window {
new265webjs: new265webJsFn
}
}
export default class H265webjsModule {
static createPlayer: (url: string, config: Web265JsConfig) => New265WebJs
static clear(): void
}

View File

@ -0,0 +1,32 @@
/*********************************************************
* LICENSE: LICENSE-Free_CN.MD
*
* Author: Numberwolf - ChangYanlong
* QQ: 531365872
* QQ Group:925466059
* Wechat: numberwolf11
* Discord: numberwolf#8694
* E-Mail: porschegt23@foxmail.com
* Github: https://github.com/numberwolf/h265web.js
*
* 作者: 小老虎(Numberwolf)(常炎隆)
* QQ: 531365872
* QQ群: 531365872
* 微信: numberwolf11
* Discord: numberwolf#8694
* 邮箱: porschegt23@foxmail.com
* 博客: https://www.jianshu.com/u/9c09c1e00fd1
* Github: https://github.com/numberwolf/h265web.js
*
**********************************************************/
require('./h265webjs-v20221106');
export default class h265webjs {
static createPlayer(videoURL, config) {
return window.new265webjs(videoURL, config);
}
static clear() {
global.STATICE_MEM_playerCount = -1;
global.STATICE_MEM_playerIndexPtr = 0;
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,683 @@
declare namespace Jessibuca {
/** 超时信息 */
enum TIMEOUT {
/** 当play()的时候,如果没有数据返回 */
loadingTimeout = 'loadingTimeout',
/** 当播放过程中如果超过timeout之后没有数据渲染 */
delayTimeout = 'delayTimeout',
}
/** 错误信息 */
enum ERROR {
/** 播放错误url 为空的时候,调用 play 方法 */
playError = 'playError',
/** http 请求失败 */
fetchError = 'fetchError',
/** websocket 请求失败 */
websocketError = 'websocketError',
/** webcodecs 解码 h265 失败 */
webcodecsH265NotSupport = 'webcodecsH265NotSupport',
/** mediaSource 解码 h265 失败 */
mediaSourceH265NotSupport = 'mediaSourceH265NotSupport',
/** wasm 解码失败 */
wasmDecodeError = 'wasmDecodeError',
}
interface Config {
/**
*
* * string document.getElementById('id')
* */
container: HTMLElement | string;
/**
*
*/
videoBuffer?: number;
/**
* worker地址
* * decoder.js文件 decoder.js decoder.wasm文件必须是放在同一个目录下面 */
decoder?: string;
/**
* 使
*/
forceNoOffscreen?: boolean;
/**
* 'visibilityState''hidden'
*/
hiddenAutoPause?: boolean;
/**
* `false`
*/
hasAudio?: boolean;
/**
* 0()180270
*/
rotate?: boolean;
/**
* 1. `true`,canvas区域,, `setScaleMode(1)`
* 2. `false`canvas区域, `setScaleMode(0)`
*/
isResize?: boolean;
/**
* 1. `true`,canvas区域,,, `setScaleMode(2)`
*/
isFullResize?: boolean;
/**
* 1. `true`ws协议不检验是否以.flv为依据
*/
isFlv?: boolean;
/**
*
*/
debug?: boolean;
/**
* 1. ,
* 2. (loading)(heart),,timeout事件
*/
timeout?: number;
/**
* 1. ,
* 2. ,,timeout事件
*/
heartTimeout?: number;
/**
* 1. ,
* 2. ,,timeout事件
*/
loadingTimeout?: number;
/**
*
*/
supportDblclickFullscreen?: boolean;
/**
*
*/
showBandwidth?: boolean;
/**
*
*/
operateBtns?: {
/** 是否显示全屏按钮 */
fullscreen?: boolean;
/** 是否显示截图按钮 */
screenshot?: boolean;
/** 是否显示播放暂停按钮 */
play?: boolean;
/** 是否显示声音按钮 */
audio?: boolean;
/** 是否显示录制按 */
record?: boolean;
};
/**
* , canvas标签渲染视频并不会像video标签那样保持屏幕常亮
*/
keepScreenOn?: boolean;
/**
*
*/
isNotMute?: boolean;
/**
*
*/
loadingText?: string;
/**
*
*/
background?: string;
/**
* MediaSource硬解码
* * H.264Safari on iOS不支持
* * forceNoOffscreen false ()
*/
useMSE?: boolean;
/**
* Webcodecs硬解码
* * H.264 (chrome 94https或者localhost环境)
* * forceNoOffscreen false )
* */
useWCS?: boolean;
/**
*
* esc -> 退arrowUp -> arrowDown ->
*/
hotKey?: boolean;
/**
* 使MSE或者Webcodecs H265的时候wasm模式
* false Error true wasm模式播放
*/
autoWasm?: boolean;
/**
* heartTimeout ,
*/
heartTimeoutReplay?: boolean,
/**
* heartTimeoutReplay
*/
heartTimeoutReplayTimes?: number,
/**
* loadingTimeout loading之后自动再播放,
*/
loadingTimeoutReplay?: boolean,
/**
* heartTimeoutReplay
*/
loadingTimeoutReplayTimes?: number
/**
* wasm解码报错之后
*/
wasmDecodeErrorReplay?: boolean,
/**
* https://github.com/langhuihui/jessibuca/issues/152 解决方案
* WebGL图像预处理默认每次取4字节的数据540x960分辨率下的UV分量宽度是540/2=2704绿
*/
openWebglAlignment?: boolean,
/**
* webcodecs硬解码是否通过video标签渲染
*/
wcsUseVideoRender?: boolean,
/**
*
*/
controlAutoHide?: boolean,
/**
*
*/
recordType?: 'webm' | 'mp4',
/**
* 使web全屏(90)
*/
useWebFullScreen?: boolean,
/**
* 使
*/
autoUseSystemFullScreen?: boolean,
}
}
declare class Jessibuca {
constructor(config?: Jessibuca.Config);
/**
*
@example
// 开启
jessibuca.setDebug(true)
// 关闭
jessibuca.setDebug(false)
*/
setDebug(flag: boolean): void;
/**
*
@example
jessibuca.mute()
*/
mute(): void;
/**
*
@example
jessibuca.cancelMute()
*/
cancelMute(): void;
/**
*
*
* iPhonechrome等要求自动播放时使
*
* https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
*/
audioResume(): void;
/**
*
* ,
* ,,timeout事件
@example
jessibuca.setTimeout(10)
jessibuca.on('timeout',function(){
//
});
*/
setTimeout(): void;
/**
* @param mode
* 0 canvas区域, `isResize` false
*
* 1 ,canvas区域,, `isResize` true
*
* 2 ,canvas区域,,, `isFullResize` true
@example
jessibuca.setScaleMode(0)
jessibuca.setScaleMode(1)
jessibuca.setScaleMode(2)
*/
setScaleMode(mode: number): void;
/**
*
*
* pause `play()`
@example
jessibuca.pause().then(()=>{
console.log('pause success')
jessibuca.play().then(()=>{
}).catch((e)=>{
})
}).catch((e)=>{
console.log('pause error',e);
})
*/
pause(): Promise<void>;
/**
* ,
@example
jessibuca.close();
*/
close(): void;
/**
*
@example
jessibuca.destroy()
*/
destroy(): void;
/**
*
@example
jessibuca.clearView()
*/
clearView(): void;
/**
*
@example
jessibuca.play('url').then(()=>{
console.log('play success')
}).catch((e)=>{
console.log('play error',e)
})
// 添加请求头
jessibuca.play('url',{headers:{'Authorization':'test111'}}).then(()=>{
console.log('play success')
}).catch((e)=>{
console.log('play error',e)
})
*/
play(url?: string, options?: {
headers: Object
}): Promise<void>;
/**
*
*/
resize(): void;
/**
*
*
* `videoBuffer`
*
@example
// 设置 200ms 缓冲
jessibuca.setBufferTime(0.2)
*/
setBufferTime(time: number): void;
/**
* 0() 180270
*
* > iOS没有全屏API *
@example
jessibuca.setRotate(0)
jessibuca.setRotate(90)
jessibuca.setRotate(270)
*/
setRotate(deg: number): void;
/**
*
* 0 1
*
* > mute cancelMute setVolume(0) mute方法mute setVolume(0)0
* @param volume 0;1
@example
jessibuca.setVolume(0.2)
jessibuca.setVolume(0)
jessibuca.setVolume(1)
*/
setVolume(volume: number): void;
/**
*
@example
var result = jessibuca.hasLoaded()
console.log(result) // true
*/
hasLoaded(): boolean;
/**
* , canvas标签渲染视频并不会像video标签那样保持屏幕常亮
* H5目前在chrome\edge 84, android chrome 84API, https页面
*
@example
jessibuca.setKeepScreenOn()
*/
setKeepScreenOn(): boolean;
/**
* ()
@example
jessibuca.setFullscreen(true)
//
jessibuca.setFullscreen(false)
*/
setFullscreen(flag: boolean): void;
/**
*
*
* @param filename , , `时间戳`
* @param format , png或jpeg或者webp , `png`
* @param quality , jpeg或者webp时0 ~ 1 , `0.92`
* @param type , download或者base64或者blob`download`
@example
jessibuca.screenshot("test","png",0.5)
const base64 = jessibuca.screenshot("test","png",0.5,'base64')
const fileBlob = jessibuca.screenshot("test",'blob')
*/
screenshot(filename?: string, format?: string, quality?: number, type?: string): void;
/**
*
* @param fileName
* @param fileType webmwebm mp4
@example
jessibuca.startRecord('xxx','webm')
*/
startRecord(fileName: string, fileType: string): void;
/**
*
@example
jessibuca.stopRecordAndSave()
*/
stopRecordAndSave(): void;
/**
*
@example
var result = jessibuca.isPlaying()
console.log(result) // true
*/
isPlaying(): boolean;
/**
*
@example
var result = jessibuca.isMute()
console.log(result) // true
*/
isMute(): boolean;
/**
*
@example
var result = jessibuca.isRecording()
console.log(result) // true
*/
isRecording(): boolean;
/**
* /
* @param isShow
*
* @example
* jessibuca.toggleControlBar(true) // 显示
* jessibuca.toggleControlBar(false) // 隐藏
* jessibuca.toggleControlBar() // 切换 隐藏/显示
*/
toggleControlBar(isShow:boolean): void;
/**
*
*/
getControlBarShow(): boolean;
/**
* jessibuca
* @example
* jessibuca.on("load",function(){console.log('load')})
*/
on(event: 'load', callback: () => void): void;
/**
* ms
* @example
* jessibuca.on('timeUpdate',function (ts) {console.log('timeUpdate',ts);})
*/
on(event: 'timeUpdate', callback: () => void): void;
/**
* 2
* @example
* jessibuca.on("videoInfo",function(data){console.log('width:',data.width,'height:',data.width)})
*/
on(event: 'videoInfo', callback: (data: {
/** 视频宽 */
width: number;
/** 视频高 */
height: number;
}) => void): void;
/**
* 2
* @example
* jessibuca.on("audioInfo",function(data){console.log('numOfChannels:',data.numOfChannels,'sampleRate',data.sampleRate)})
*/
on(event: 'audioInfo', callback: (data: {
/** 声频通道 */
numOfChannels: number;
/** 采样率 */
sampleRate: number;
}) => void): void;
/**
*
* @example
* jessibuca.on("log",function(data){console.log('data:',data)})
*/
on(event: 'log', callback: () => void): void;
/**
*
* @example
* jessibuca.on("error",function(error){
if(error === Jessibuca.ERROR.fetchError){
//
}
else if(error === Jessibuca.ERROR.webcodecsH265NotSupport){
//
}
console.log('error:',error)
})
*/
on(event: 'error', callback: (err: Jessibuca.ERROR) => void): void;
/**
* KB 1,
* @example
* jessibuca.on("kBps",function(data){console.log('kBps:',data)})
*/
on(event: 'kBps', callback: (value: number) => void): void;
/**
*
* @example
* jessibuca.on("start",function(){console.log('start render')})
*/
on(event: 'start', callback: () => void): void;
/**
* ,
* @example
* jessibuca.on("timeout",function(error){console.log('timeout:',error)})
*/
on(event: 'timeout', callback: (error: Jessibuca.TIMEOUT) => void): void;
/**
* play()
* @example
* jessibuca.on("loadingTimeout",function(){console.log('timeout')})
*/
on(event: 'loadingTimeout', callback: () => void): void;
/**
* timeout之后没有数据渲染
* @example
* jessibuca.on("delayTimeout",function(){console.log('timeout')})
*/
on(event: 'delayTimeout', callback: () => void): void;
/**
*
* @example
* jessibuca.on("fullscreen",function(flag){console.log('is fullscreen',flag)})
*/
on(event: 'fullscreen', callback: () => void): void;
/**
*
* @example
* jessibuca.on("play",function(flag){console.log('play')})
*/
on(event: 'play', callback: () => void): void;
/**
*
* @example
* jessibuca.on("pause",function(flag){console.log('pause')})
*/
on(event: 'pause', callback: () => void): void;
/**
* boolean值
* @example
* jessibuca.on("mute",function(flag){console.log('is mute',flag)})
*/
on(event: 'mute', callback: () => void): void;
/**
* 1
* @example
* jessibuca.on("stats",function(s){console.log("stats is",s)})
*/
on(event: 'stats', callback: (stats: {
/** 当前缓冲区时长,单位毫秒 */
buf: number;
/** 当前视频帧率 */
fps: number;
/** 当前音频码率单位byte */
abps: number;
/** 当前视频码率单位byte */
vbps: number;
/** 当前视频帧pts单位毫秒 */
ts: number;
}) => void): void;
/**
* 1
* @param performance 0: 表示卡顿,1: 表示流畅,2: 表示非常流程
* @example
* jessibuca.on("performance",function(performance){console.log("performance is",performance)})
*/
on(event: 'performance', callback: (performance: 0 | 1 | 2) => void): void;
/**
*
* @example
* jessibuca.on("recordStart",function(){console.log("record start")})
*/
on(event: 'recordStart', callback: () => void): void;
/**
*
* @example
* jessibuca.on("recordEnd",function(){console.log("record end")})
*/
on(event: 'recordEnd', callback: () => void): void;
/**
* 1s一次
* @example
* jessibuca.on("recordingTimestamp",function(timestamp){console.log("recordingTimestamp is",timestamp)})
*/
on(event: 'recordingTimestamp', callback: (timestamp: number) => void): void;
/**
* play方法 -> -> -> ->
* @param event
* @param callback
*/
on(event: 'playToRenderTimes', callback: (times: {
playInitStart: number, // 1 初始化
playStart: number, // 2 初始化
streamStart: number, // 3 网络请求
streamResponse: number, // 4 网络请求
demuxStart: number, // 5 解封装
decodeStart: number, // 6 解码
videoStart: number, // 7 渲染
playTimestamp: number,// playStart- playInitStart
streamTimestamp: number,// streamStart - playStart
streamResponseTimestamp: number,// streamResponse - streamStart
demuxTimestamp: number, // demuxStart - streamResponse
decodeTimestamp: number, // decodeStart - demuxStart
videoTimestamp: number,// videoStart - decodeStart
allTimestamp: number // videoStart - playInitStart
}) => void): void
/**
*
*
@example
jessibuca.on("load",function(){console.log('load')})
*/
on(event: string, callback: Function): void;
}
export default Jessibuca;

File diff suppressed because one or more lines are too long

11
wvpweb/src/App.vue Normal file
View File

@ -0,0 +1,11 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>

View File

@ -0,0 +1,131 @@
import request from '@/utils/request'
// 云端录像API
export function getPlayPath(id) {
return request({
method: 'get',
url: `/api/cloud/record/play/path`,
params: {
recordId: id
}
})
}
export function queryListByData(params) {
const { app, stream, year, month, mediaServerId } = params
return request({
method: 'get',
url: `/api/cloud/record/date/list`,
params: {
app: app,
stream: stream,
year: year,
month: month,
mediaServerId: mediaServerId
}
})
}
export function loadRecord(params) {
const { app, stream, cloudRecordId } = params
return request({
method: 'get',
url: `/api/cloud/record/loadRecord`,
params: {
app: app,
stream: stream,
cloudRecordId: cloudRecordId
}
})
}
export function seek(params) {
const { mediaServerId, app, stream, seek, schema } = params
return request({
method: 'get',
url: `/api/cloud/record/seek`,
params: {
mediaServerId: mediaServerId,
app: app,
stream: stream,
seek: seek,
schema: schema
}
})
}
export function speed(params) {
const { mediaServerId, app, stream, speed, schema } = params
return request({
method: 'get',
url: `/api/cloud/record/speed`,
params: {
mediaServerId: mediaServerId,
app: app,
stream: stream,
speed: speed,
schema: schema
}
})
}
export function addTask(params) {
const { app, stream, mediaServerId, startTime, endTime } = params
return request({
method: 'get',
url: `/api/cloud/record/task/add`,
params: {
app: app,
stream: stream,
mediaServerId: mediaServerId,
startTime: startTime,
endTime: endTime
}
})
}
export function queryTaskList(params) {
const { mediaServerId, isEnd } = params
return request({
method: 'get',
url: `/api/cloud/record/task/list`,
params: {
mediaServerId: mediaServerId,
isEnd: isEnd
}
})
}
export function deleteRecord(ids) {
return request({
method: 'delete',
url: `/api/cloud/record/delete`,
data: {
ids: ids
}
})
}
export function queryList(params) {
const { app, stream, query, callId, startTime, endTime, mediaServerId, page, count, ascOrder } = params
return request({
method: 'get',
url: `/api/cloud/record/list`,
params: {
app: app,
stream: stream,
query: query,
callId: callId,
startTime: startTime,
endTime: endTime,
mediaServerId: mediaServerId,
page: page,
count: count,
ascOrder: ascOrder
}
})
}

View File

@ -0,0 +1,658 @@
import request from '@/utils/request'
// 通用通道API
export function queryOne(id) {
return request({
method: 'get',
url: '/api/common/channel/one',
params: {
id: id
}
})
}
export function getIndustryList() {
return request({
method: 'get',
url: '/api/common/channel/industry/list'
})
}
export function getTypeList() {
return request({
method: 'get',
url: '/api/common/channel/type/list'
})
}
export function getNetworkIdentificationList() {
return request({
method: 'get',
url: '/api/common/channel/network/identification/list'
})
}
export function update(data) {
return request({
method: 'post',
url: '/api/common/channel/update',
data: data
})
}
export function reset(data) {
return request({
method: 'post',
url: '/api/common/channel/reset',
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: '/api/common/channel/add',
data: data
})
}
export function getList(params) {
const { page, count, query, online, hasRecordPlan, channelType, civilCode, parentDeviceId } = params
return request({
method: 'get',
url: '/api/common/channel/list',
params: {
page: page,
count: count,
channelType: channelType,
query: query,
online: online,
hasRecordPlan: hasRecordPlan,
civilCode: civilCode,
parentDeviceId: parentDeviceId
}
})
}
export function getCivilCodeList(params) {
const { page, count, channelType, query, online, civilCode } = params
return request({
method: 'get',
url: '/api/common/channel/civilcode/list',
params: {
page: page,
count: count,
channelType: channelType,
query: query,
online: online,
civilCode: civilCode
}
})
}
export function getUnusualCivilCodeList(params) {
const { page, count, channelType, query, online } = params
return request({
method: 'get',
url: '/api/common/channel/civilCode/unusual/list',
params: {
page: page,
count: count,
channelType: channelType,
query: query,
online: online
}
})
}
export function getUnusualParentList(params) {
const { page, count, channelType, query, online } = params
return request({
method: 'get',
url: '/api/common/channel/parent/unusual/list',
params: {
page: page,
count: count,
channelType: channelType,
query: query,
online: online
}
})
}
export function clearUnusualCivilCodeList(params) {
const { all, channelIds } = params
return request({
method: 'post',
url: '/api/common/channel/civilCode/unusual/clear',
data: {
all: all,
channelIds: channelIds
}
})
}
export function clearUnusualParentList(params) {
const { all, channelIds } = params
return request({
method: 'post',
url: '/api/common/channel/parent/unusual/clear',
data: {
all: all,
channelIds: channelIds
}
})
}
export function getParentList(params) {
const { page, count, channelType, query, online, groupDeviceId } = params
return request({
method: 'get',
url: '/api/common/channel/parent/list',
params: {
page: page,
count: count,
channelType: channelType,
query: query,
online: online,
groupDeviceId: groupDeviceId
}
})
}
export function addToRegion(params) {
const { civilCode, channelIds } = params
return request({
method: 'post',
url: '/api/common/channel/region/add',
data: {
civilCode: civilCode,
channelIds: channelIds
}
})
}
export function deleteFromRegion(channels) {
return request({
method: 'post',
url: '/api/common/channel/region/delete',
data: {
channelIds: channels
}
})
}
export function addDeviceToRegion(params) {
const { civilCode, deviceIds } = params
return request({
method: 'post',
url: '/api/common/channel/region/device/add',
data: {
civilCode: civilCode,
deviceIds: deviceIds
}
})
}
export function deleteDeviceFromRegion(deviceIds) {
return request({
method: 'post',
url: '/api/common/channel/region/device/delete',
data: {
deviceIds: deviceIds
}
})
}
export function addToGroup(params) {
const { parentId, businessGroup, channelIds } = params
return request({
method: 'post',
url: '/api/common/channel/group/add',
data: {
parentId: parentId,
businessGroup: businessGroup,
channelIds: channelIds
}
})
}
export function deleteFromGroup(channels) {
return request({
method: 'post',
url: '/api/common/channel/group/delete',
data: {
channelIds: channels
}
})
}
export function addDeviceToGroup(params) {
const { parentId, businessGroup, deviceIds } = params
return request({
method: 'post',
url: '/api/common/channel/group/device/add',
data: {
parentId: parentId,
businessGroup: businessGroup,
deviceIds: deviceIds
}
})
}
export function deleteDeviceFromGroup(deviceIds) {
return request({
method: 'post',
url: '/api/common/channel/group/device/delete',
data: {
deviceIds: deviceIds
}
})
}
export function playChannel(channelId) {
return request({
method: 'get',
url: '/api/common/channel/play',
params: {
channelId: channelId
}
})
}
export function stopPlayChannel(channelId) {
return request({
method: 'get',
url: '/api/common/channel/play/stop',
params: {
channelId: channelId
}
})
}
// 前端控制
export function setSpeedForScan({ channelId, scanId, speed }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/scan/set/speed',
params: {
channelId: channelId,
scanId: scanId,
speed: speed
}
})
}
export function setLeftForScan({ channelId, scanId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/scan/set/left',
params: {
channelId: channelId,
scanId: scanId
}
})
}
export function setRightForScan({ channelId, scanId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/scan/set/right',
params: {
channelId: channelId,
scanId: scanId
}
})
}
export function startScan({ channelId, scanId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/scan/start',
params: {
channelId: channelId,
scanId: scanId
}
})
}
export function stopScan({ channelId, scanId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/scan/stop',
params: {
channelId: channelId,
scanId: scanId
}
})
}
export function queryPreset(channelId) {
return request({
method: 'get',
url: '/api/common/channel/front-end/preset/query',
params: {
channelId: channelId
}
})
}
export function addPointForCruise({ channelId, tourId, presetId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/point/add',
params: {
channelId: channelId,
tourId: tourId,
presetId: presetId
}
})
}
export function deletePointForCruise({ channelId, tourId, presetId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/point/delete',
params: {
channelId: channelId,
tourId: tourId,
presetId: presetId
}
})
}
export function setCruiseSpeed({ channelId, tourId, presetId , speed }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/speed',
params: {
channelId: channelId,
tourId: tourId,
presetId: presetId,
speed: speed
}
})
}
export function setCruiseTime({ channelId, tourId, presetId, time }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/time',
params: {
channelId: channelId,
tourId: tourId,
presetId: presetId,
time: time
}
})
}
export function startCruise({ channelId, tourId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/start',
params: {
channelId: channelId,
tourId: tourId
}
})
}
export function stopCruise({ channelId, tourId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/tour/stop',
params: {
channelId: channelId,
tourId: tourId
}
})
}
export function addPreset({ channelId, presetId, presetName }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/preset/add',
params: {
channelId: channelId,
presetId: presetId,
presetName: presetName
}
})
}
export function callPreset({ channelId, presetId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/preset/call',
params: {
channelId: channelId,
presetId: presetId
}
})
}
export function deletePreset({ channelId, presetId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/preset/delete',
params: {
channelId: channelId,
presetId: presetId
}
})
}
/**
* command: on 开启 off 关闭
*/
export function auxiliary({ channelId, command, auxiliaryId }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/auxiliary',
params: {
channelId: channelId,
command: command,
auxiliaryId: auxiliaryId
}
})
}
/**
* command: on 开启 off 关闭
*/
export function wiper({ channelId, command }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/wiper',
params: {
channelId: channelId,
command: command
}
})
}
export function ptz({ channelId, command, panSpeed, tiltSpeed, zoomSpeed }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/ptz',
params: {
channelId: channelId,
command: command,
panSpeed: panSpeed,
tiltSpeed: tiltSpeed,
zoomSpeed: zoomSpeed
}
})
}
export function iris({ channelId, command, speed }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/fi/iris',
params: {
channelId: channelId,
command: command,
speed: speed
}
})
}
export function focus({ channelId, command, speed }) {
return request({
method: 'get',
url: '/api/common/channel/front-end/fi/focus',
params: {
channelId: channelId,
command: command,
speed: speed
}
})
}
export function queryRecord({ channelId, startTime, endTime }) {
return request({
method: 'get',
url: '/api/common/channel/playback/query',
params: {
channelId: channelId,
startTime: startTime,
endTime: endTime
}
})
}
export function playback({ channelId, startTime, endTime }) {
return request({
method: 'get',
url: '/api/common/channel/playback',
params: {
channelId: channelId,
startTime: startTime,
endTime: endTime
}
})
}
export function stopPlayback({ channelId, stream }) {
return request({
method: 'get',
url: '/api/common/channel/playback/stop',
params: {
channelId: channelId,
stream: stream
}
})
}
export function pausePlayback({ channelId, stream}) {
return request({
method: 'get',
url: '/api/common/channel/playback/pause',
params: {
channelId: channelId,
stream: stream
}
})
}
export function resumePlayback({ channelId, stream}) {
return request({
method: 'get',
url: '/api/common/channel/playback/resume',
params: {
channelId: channelId,
stream: stream
}
})
}
export function seekPlayback({ channelId, stream, seekTime}) {
return request({
method: 'get',
url: '/api/common/channel/playback/seek',
params: {
channelId: channelId,
stream: stream,
seekTime: seekTime
}
})
}
export function speedPlayback({ channelId, stream, speed}) {
return request({
method: 'get',
url: '/api/common/channel/playback/speed',
params: {
channelId: channelId,
stream: stream,
speed: speed
}
})
}
export function getAllForMap({ query, online, hasRecordPlan, channelType }) {
return request({
method: 'get',
url: '/api/common/channel/map/list',
params: {
query: query,
online: online,
hasRecordPlan: hasRecordPlan,
channelType: channelType
}
})
}
export function saveLevel(data) {
return request({
method: 'post',
url: '/api/common/channel/map/save-level',
data: data
})
}
export function resetLevel() {
return request({
method: 'post',
url: '/api/common/channel/map/reset-level'
})
}
export function clearThin(id) {
return request({
method: 'get',
url: '/api/common/channel/map/thin/clear',
params: {
id: id
}
})
}
export function thinProgress(id) {
return request({
method: 'get',
url: '/api/common/channel/map/thin/progress',
params: {
id: id
}
})
}
export function saveThin(id) {
return request({
method: 'get',
url: '/api/common/channel/map/thin/save',
params: {
id: id
}
})
}
export function drawThin(data) {
return request({
method: 'post',
url: '/api/common/channel/map/thin/draw',
data: data
})
}
export function test() {
return request({
method: 'get',
url: '/api/sy/camera/list/ids',
params: {
deviceIds: ['a', 'b', 'c'].join(','),
geoCoordSys: 'GCJ02',
traditional: true
}
})
}

243
wvpweb/src/api/device.js Normal file
View File

@ -0,0 +1,243 @@
import request from '@/utils/request'
// 国标设备API
export function queryDeviceSyncStatus(deviceId) {
return request({
method: 'get',
url: `/api/device/query/${deviceId}/sync_status`
})
}
export function queryDevices(params) {
const { page, count, query, status } = params
return request({
method: 'get',
url: `/api/device/query/devices`,
params: {
page: page,
count: count,
query: query,
status: status
}
})
}
export function deleteDevice(deviceId) {
return request({
method: 'delete',
url: `/api/device/query/devices/${deviceId}/delete`
})
}
export function sync(deviceId) {
return request({
method: 'get',
url: `/api/device/query/devices/${deviceId}/sync`
})
}
export function updateDeviceTransport(deviceId, streamMode) {
return request({
method: 'post',
url: `/api/device/query/transport/${deviceId}/${streamMode}`
})
}
export function setGuard(deviceId) {
return request({
method: 'get',
url: `/api/device/control/guard`,
params: {
deviceId: deviceId,
guardCmd: 'SetGuard'
}
})
}
export function resetGuard(deviceId) {
return request({
method: 'get',
url: `/api/device/control/guard`,
params: {
deviceId: deviceId,
guardCmd: 'ResetGuard'
}
})
}
export function subscribeCatalog(params) {
const { id, cycle } = params
return request({
method: 'get',
url: `/api/device/query/subscribe/catalog`,
params: {
id: id,
cycle: cycle
}
})
}
export function subscribeMobilePosition(params) {
const { id, cycle, interval } = params
return request({
method: 'get',
url: `/api/device/query/subscribe/mobile-position`,
params: {
id: id,
cycle: cycle,
interval: interval
}
})
}
export function queryBasicParam(deviceId) {
return request({
method: 'get',
url: `/api/device/config/query/${deviceId}/BasicParam`
})
}
export function queryChannelOne(params) {
const { deviceId, channelDeviceId } = params
return request({
method: 'get',
url: '/api/device/query/channel/one',
params: {
deviceId: deviceId,
channelDeviceId: channelDeviceId
}
})
}
export function queryChannels(deviceId, params) {
const { page, count, query, online, channelType, catalogUnderDevice } = params
return request({
method: 'get',
url: `/api/device/query/devices/${deviceId}/channels`,
params: {
page: page,
count: count,
query: query,
online: online,
channelType: channelType,
catalogUnderDevice: catalogUnderDevice
}
})
}
export function queryHasStreamChannels(params) {
const {page, count, query} = params
return request({
method: 'get',
url: `/api/device/query/streams`,
params: {
page: page,
count: count,
query: query
}
})
}
export function deviceRecord(params) {
const { deviceId, channelId, recordCmdStr } = params
return request({
method: 'get',
url: `/api/device/control/record`,
params: {
deviceId: deviceId,
channelId: channelId,
recordCmdStr: recordCmdStr
}
})
}
export function querySubChannels(params, deviceId, parentChannelId) {
const { page, count, query, online, channelType } = params
return request({
method: 'get',
url: `/api/device/query/sub_channels/${deviceId}/${parentChannelId}/channels`,
params: {
page: page,
count: count,
query: query,
online: online,
channelType: channelType
}
})
}
export function queryChannelTree(params) {
const { parentId, page, count } = params
return request({
method: 'get',
url: `/api/device/query/tree/channel/${this.deviceId}`,
params: {
parentId: parentId,
page: page,
count: count
}
})
}
export function changeChannelAudio(params) {
const { channelId, audio } = params
return request({
method: 'post',
url: `/api/device/query/channel/audio`,
params: {
channelId: channelId,
audio: audio
}
})
}
export function updateChannelStreamIdentification(params) {
const { deviceDbId, streamIdentification, id } = params
return request({
method: 'post',
url: `/api/device/query/channel/stream/identification/update/`,
params: {
deviceDbId: deviceDbId,
id: id,
streamIdentification: streamIdentification
}
})
}
export function update(data) {
return request({
method: 'post',
url: `/api/device/query/device/update`,
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: `/api/device/query/device/add`,
data: data
})
}
export function queryDeviceOne(deviceId) {
return request({
method: 'get',
url: `/api/device/query/devices/${deviceId}`
})
}
export function queryDeviceTree(params, deviceId) {
const { page, count, parentId, onlyCatalog } = params
return request({
method: 'get',
url: `/api/device/query/tree/${deviceId}`,
params: {
page: page,
count: count,
parentId: parentId,
onlyCatalog: onlyCatalog
}
})
}

218
wvpweb/src/api/frontEnd.js Normal file
View File

@ -0,0 +1,218 @@
import request from '@/utils/request'
// 前端控制
export function setSpeedForScan([deviceId, channelDeviceId, scanId, speed]) {
return request({
method: 'get',
url: `/api/front-end/scan/set/speed/${deviceId}/${channelDeviceId}`,
params: {
scanId: scanId,
speed: speed
}
})
}
export function setLeftForScan([deviceId, channelDeviceId, scanId]) {
return request({
method: 'get',
url: `/api/front-end/scan/set/left/${deviceId}/${channelDeviceId}`,
params: {
scanId: scanId
}
})
}
export function setRightForScan([deviceId, channelDeviceId, scanId]) {
return request({
method: 'get',
url: `/api/front-end/scan/set/right/${deviceId}/${channelDeviceId}`,
params: {
scanId: scanId
}
})
}
export function startScan([deviceId, channelDeviceId, scanId]) {
return request({
method: 'get',
url: `/api/front-end/scan/start/${deviceId}/${channelDeviceId}`,
params: {
scanId: scanId
}
})
}
export function stopScan([deviceId, channelDeviceId, scanId]) {
return request({
method: 'get',
url: `/api/front-end/scan/stop/${deviceId}/${channelDeviceId}`,
params: {
scanId: scanId
}
})
}
export function queryPreset([deviceId, channelDeviceId]) {
return request({
method: 'get',
url: `/api/front-end/preset/query/${deviceId}/${channelDeviceId}`
})
}
export function addPointForCruise([deviceId, channelDeviceId, cruiseId, presetId]) {
return request({
method: 'get',
url: `/api/front-end/cruise/point/add/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId,
presetId: presetId
}
})
}
export function deletePointForCruise([deviceId, channelDeviceId, cruiseId, presetId]) {
return request({
method: 'get',
url: `/api/front-end/cruise/point/delete/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId,
presetId: presetId
}
})
}
export function setCruiseSpeed([deviceId, channelDeviceId, cruiseId, cruiseSpeed]) {
return request({
method: 'get',
url: `/api/front-end/cruise/speed/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId,
speed: cruiseSpeed
}
})
}
export function setCruiseTime([deviceId, channelDeviceId, cruiseId, cruiseTime]) {
return request({
method: 'get',
url: `/api/front-end/cruise/time/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId,
time: cruiseTime
}
})
}
export function startCruise([deviceId, channelDeviceId, cruiseId]) {
return request({
method: 'get',
url: `/api/front-end/cruise/start/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId
}
})
}
export function stopCruise([deviceId, channelDeviceId, cruiseId]) {
return request({
method: 'get',
url: `/api/front-end/cruise/stop/${deviceId}/${channelDeviceId}`,
params: {
cruiseId: cruiseId
}
})
}
export function addPreset([deviceId, channelDeviceId, presetId]) {
return request({
method: 'get',
url: `/api/front-end/preset/add/${deviceId}/${channelDeviceId}`,
params: {
presetId: presetId
}
})
}
export function callPreset([deviceId, channelDeviceId, presetId]) {
return request({
method: 'get',
url: `/api/front-end/preset/call/${deviceId}/${channelDeviceId}`,
params: {
presetId: presetId
}
})
}
export function deletePreset([deviceId, channelDeviceId, presetId]) {
return request({
method: 'get',
url: `/api/front-end/preset/delete/${deviceId}/${channelDeviceId}`,
params: {
presetId: presetId
}
})
}
/**
* command: on 开启 off 关闭
*/
export function auxiliary([deviceId, channelDeviceId, command, switchId]) {
return request({
method: 'get',
url: `/api/front-end/auxiliary/${deviceId}/${channelDeviceId}`,
params: {
command: command,
switchId: switchId
}
})
}
/**
* command: on 开启 off 关闭
*/
export function wiper([deviceId, channelDeviceId, command]) {
return request({
method: 'get',
url: `/api/front-end/wiper/${deviceId}/${channelDeviceId}`,
params: {
command: command
}
})
}
export function ptz([deviceId, channelId, command, horizonSpeed, verticalSpeed, zoomSpeed]) {
return request({
method: 'get',
url: `/api/front-end/ptz/${deviceId}/${channelId}`,
params: {
command: command,
horizonSpeed: horizonSpeed,
verticalSpeed: verticalSpeed,
zoomSpeed: zoomSpeed
}
})
}
export function iris([deviceId, channelId, command, speed]) {
return request({
method: 'get',
url: `/api/front-end/fi/iris/${deviceId}/${channelId}`,
params: {
command: command,
speed: speed
}
})
}
export function focus([deviceId, channelDeviceId, command, speed]) {
return request({
method: 'get',
url: `/api/front-end/fi/focus/${deviceId}/${channelDeviceId}`,
params: {
command: command,
speed: speed
}
})
}

View File

@ -0,0 +1,33 @@
import request from '@/utils/request'
export function query([deviceId, channelId, startTime, endTime]) {
return request({
method: 'get',
url: '/api/gb_record/query/' + deviceId + '/' + channelId + '?startTime=' + startTime + '&endTime=' + endTime
})
}
export function startDownLoad([deviceId, channelId, startTime, endTime, downloadSpeed]) {
return request({
url: '/api/gb_record/download/start/' + deviceId + '/' + channelId + '?startTime=' + startTime + '&endTime=' +
endTime + '&downloadSpeed=' + downloadSpeed
})
}
export function stopDownLoad(deviceId, channelId, streamId) {
return request({
method: 'get',
url: '/api/gb_record/download/stop/' + deviceId + '/' + channelId + '/' + streamId
})
}
export function queryDownloadProgress([deviceId, channelId, streamId]) {
return request({
method: 'get',
url: `/api/gb_record/download/progress/${deviceId}/${channelId}/${streamId}`
})
}

69
wvpweb/src/api/group.js Normal file
View File

@ -0,0 +1,69 @@
import request from '@/utils/request'
// 分组API
export function update(data) {
return request({
method: 'post',
url: '/api/group/update',
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: '/api/group/add',
data: data
})
}
export function getTreeList({ query, parent, hasChannel, page, count }) {
return request({
method: 'get',
url: `/api/group/tree/list`,
params: {
query: query,
parent: parent,
hasChannel: hasChannel,
page: page,
count: count
}
})
}
export function deleteGroup(id) {
return request({
method: 'delete',
url: `/api/group/delete`,
params: {
id: id
}
})
}
export function getPath(params) {
const { deviceId, businessGroup } = params
return request({
method: 'get',
url: `/api/group/path`,
params: {
deviceId: deviceId,
businessGroup: businessGroup
}
})
}
export function queryTree(params) {
const { page, count, query } = params
return request({
method: 'get',
url: `/api/group/tree/query`,
params: {
query: query,
page: page,
count: count
}
})
}
export function sync() {
return request({
method: 'get',
url: `/api/group/sync`,
})
}

371
wvpweb/src/api/jtDevice.js Normal file
View File

@ -0,0 +1,371 @@
import request from '@/utils/request'
// 部标设备API
export function queryDevices({ page, count, query, online }) {
return request({
method: 'get',
url: '/api/jt1078/terminal/list',
params: {
page: page,
count: count,
query: query,
online: online
}
})
}
export function queryDeviceById(deviceId) {
return request({
method: 'get',
url: '/api/jt1078/terminal/query',
params: {
deviceId: deviceId
}
})
}
export function update(form) {
return request({
method: 'post',
url: '/api/jt1078/terminal/update',
params: form
})
}
export function add(form) {
return request({
method: 'post',
url: '/api/jt1078/terminal/add',
params: form
})
}
export function deleteDevice(phoneNumber) {
return request({
method: 'delete',
url: '/api/jt1078/terminal/delete',
params: {
phoneNumber: phoneNumber
}
})
}
export function queryChannels(params) {
const { page, count, query, deviceId } = params
return request({
method: 'get',
url: '/api/jt1078/terminal/channel/list',
params: {
page: page,
count: count,
query: query,
deviceId: deviceId
}
})
}
export function play(params) {
const { phoneNumber, channelId, type } = params
return request({
method: 'get',
url: '/api/jt1078/live/start',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
type: type
}
})
}
export function stopPlay(params) {
const { phoneNumber, channelId } = params
return request({
method: 'get',
url: '/api/jt1078/live/stop',
params: {
phoneNumber: phoneNumber,
channelId: channelId
}
})
}
export function updateChannel(data) {
return request({
method: 'post',
url: '/api/jt1078/terminal/channel/update',
data: data
})
}
export function addChannel(data) {
return request({
method: 'post',
url: '/api/jt1078/terminal/channel/add',
data: data
})
}
export function ptz(params) {
const { phoneNumber, channelId, command, speed } = params
return request({
method: 'get',
url: '/api/jt1078/ptz',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
command: command,
speed: speed
}
})
}
export function wiper(params) {
const { phoneNumber, channelId, command } = params
return request({
method: 'get',
url: '/api/jt1078/wiper',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
command: command
}
})
}
export function fillLight(params) {
const { phoneNumber, channelId, command } = params
return request({
method: 'get',
url: '/api/jt1078/fill-light',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
command: command
}
})
}
export function queryRecordList(params) {
const { phoneNumber, channelId, startTime, endTime } = params
return request({
method: 'get',
url: '/api/jt1078/record/list',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
startTime: startTime,
endTime: endTime
}
})
}
export function startPlayback(params) {
const { phoneNumber, channelId, startTime, endTime, type, rate, playbackType, playbackSpeed } = params
return request({
method: 'get',
url: '/api/jt1078/playback/start/',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
startTime: startTime,
endTime: endTime,
type: type,
rate: rate,
playbackType: playbackType,
playbackSpeed: playbackSpeed
}
})
}
export function getRecordTempUrl({ phoneNumber, channelId, startTime, endTime, alarmSign, mediaType, streamType, storageType }) {
return request({
method: 'get',
url: '/api/jt1078/playback/downloadUrl',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
startTime: startTime,
endTime: endTime,
alarmSign: alarmSign,
mediaType: mediaType,
streamType: streamType,
storageType: storageType
}
})
}
export function controlPlayback(params) {
const { phoneNumber, channelId, command, playbackSpeed, time } = params
return request({
method: 'get',
url: '/api/jt1078/playback/control',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
command: command,
playbackSpeed: playbackSpeed,
time: time
}
})
}
export function stopPlayback(params) {
const { phoneNumber, channelId, streamId } = params
return request({
method: 'get',
url: '/api/jt1078/playback/stop/',
params: {
phoneNumber: phoneNumber,
channelId: channelId,
streamId: streamId
}
})
}
export function queryConfig(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/config/get',
params: {
phoneNumber: phoneNumber
}
})
}
export function setConfig(data) {
return request({
method: 'post',
url: '/api/jt1078/config/set',
data: data
})
}
export function queryAttribute(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/attribute',
params: {
phoneNumber: phoneNumber
}
})
}
export function linkDetection(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/link-detection',
params: {
phoneNumber: phoneNumber
}
})
}
export function queryPosition(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/position-info',
params: {
phoneNumber: phoneNumber
}
})
}
export function sendTextMessage(data) {
return request({
method: 'post',
url: '/api/jt1078/text-msg',
data: data
})
}
export function telephoneCallback({ phoneNumber, sign, destPhoneNumber }) {
return request({
method: 'get',
url: '/api/jt1078/telephone-callback',
params: {
phoneNumber: phoneNumber,
sign: sign,
destPhoneNumber: destPhoneNumber
}
})
}
export function queryDriverInfo(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/driver-information',
params: {
phoneNumber: phoneNumber
}
})
}
export function factoryReset(phoneNumber) {
return request({
method: 'post',
url: '/api/jt1078/control/factory-reset',
params: {
phoneNumber: phoneNumber
}
})
}
export function reset(phoneNumber) {
return request({
method: 'post',
url: '/api/jt1078/control/reset',
params: {
phoneNumber: phoneNumber
}
})
}
export function connection(data) {
return request({
method: 'post',
url: '/api/jt1078/control/connection',
data: data
})
}
export function controlDoor({ phoneNumber, open}) {
return request({
method: 'get',
url: '/api/jt1078/control/door',
params: {
phoneNumber: phoneNumber,
open: open
}
})
}
export function queryMediaAttribute(phoneNumber) {
return request({
method: 'get',
url: '/api/jt1078/media/attribute',
params: {
phoneNumber: phoneNumber
}
})
}
export function queryMediaData(data) {
return request({
method: 'post',
url: '/api/jt1078/media/list',
data: data
})
}
export function setPhoneBook(data) {
return request({
method: 'post',
url: '/api/jt1078/set-phone-book',
data: data
})
}
export function shooting(data) {
return request({
method: 'post',
url: '/api/jt1078/shooting',
data: data
})
}
export function startTalk({ phoneNumber, channelId }) {
return request({
method: 'get',
url: '/api/jt1078/talk/start',
params: {
phoneNumber: phoneNumber,
channelId: channelId
}
})
}
export function stopTalk({ phoneNumber, channelId }) {
return request({
method: 'get',
url: '/api/jt1078/talk/stop',
params: {
phoneNumber: phoneNumber,
channelId: channelId
}
})
}

15
wvpweb/src/api/log.js Normal file
View File

@ -0,0 +1,15 @@
import request from '@/utils/request'
export function queryList(params) {
const { query, startTime, endTime } = params
return request({
method: 'get',
url: `/api/log/list`,
params: {
query: query,
startTime: startTime,
endTime: endTime
}
})
}

142
wvpweb/src/api/platform.js Normal file
View File

@ -0,0 +1,142 @@
import request from '@/utils/request'
export function update(data) {
return request({
method: 'post',
url: '/api/platform/update',
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: '/api/platform/add',
data: data
})
}
export function exit(deviceGbId) {
return request({
method: 'get',
url: `/api/platform/exit/${deviceGbId}`
})
}
export function remove(id) {
return request({
method: 'delete',
url: `/api/platform/delete`,
params: {
id: id
}
})
}
export function pushChannel(id) {
return request({
method: 'get',
url: `/api/platform/channel/push`,
params: {
id: id
}
})
}
export function getServerConfig() {
return request({
method: 'get',
url: `/api/platform/server_config`
})
}
export function query(params) {
const { count, page, query } = params
return request({
method: 'get',
url: `/api/platform/query`,
params: {
count: count,
page: page,
query: query
}
})
}
export function getChannelList(params) {
const { page, count, query, online, channelType, platformId, hasShare } = params
return request({
method: 'get',
url: `/api/platform/channel/list`,
params: {
page: page,
count: count,
query: query,
online: online,
channelType: channelType,
platformId: platformId,
hasShare: hasShare
}
})
}
export function addChannel(params) {
const { platformId, channelIds, all } = params
return request({
method: 'post',
url: `/api/platform/channel/add`,
data: {
platformId: platformId,
channelIds: channelIds,
all: all
}
})
}
export function addChannelByDevice(params) {
const { platformId, deviceIds } = params
return request({
method: 'post',
url: `/api/platform/channel/device/add`,
data: {
platformId: platformId,
deviceIds: deviceIds
}
})
}
export function removeChannelByDevice(params) {
const { platformId, deviceIds } = params
return request({
method: 'post',
url: `/api/platform/channel/device/remove`,
data: {
platformId: platformId,
deviceIds: deviceIds
}
})
}
export function removeChannel(params) {
const { platformId, channelIds, all } = params
return request({
method: 'delete',
url: `/api/platform/channel/remove`,
data: {
platformId: platformId,
channelIds: channelIds,
all: all
}
})
}
export function updateCustomChannel(data) {
return request({
method: 'post',
url: `/api/platform/channel/custom/update`,
data: data
})
}

28
wvpweb/src/api/play.js Normal file
View File

@ -0,0 +1,28 @@
import request from '@/utils/request'
// 实时流播放API
export function play(deviceId, channelId) {
return request({
method: 'get',
url: '/api/play/start/' + deviceId + '/' + channelId
})
}
export function stop(deviceId, channelId) {
return request({
method: 'get',
url: '/api/play/stop/' + deviceId + "/" + channelId,
})
}
export function broadcastStart(deviceId, channelId, broadcastMode) {
return request({
method: 'get',
url: '/api/play/broadcast/' + deviceId + '/' + channelId + "?timeout=30&broadcastMode=" + broadcastMode
})
}
export function broadcastStop(deviceId, channelId, ) {
return request({
method: 'get',
url: '/api/play/broadcast/stop/' + deviceId + '/' + channelId
})
}

View File

@ -0,0 +1,34 @@
import request from '@/utils/request'
// 回放流播放API
export function play([deviceId, channelId, startTime, endTime]) {
return request({
method: 'get',
url: '/api/playback/start/' + deviceId + '/' + channelId + '?startTime=' + startTime + '&endTime=' + endTime
})
}
export function resume(streamId) {
return request({
method: 'get',
url: '/api/playback/resume/' + streamId
})
}
export function pause(streamId) {
return request({
method: 'get',
url: '/api/playback/pause/' + streamId
})
}
export function setSpeed([streamId, speed]) {
return request({
method: 'get',
url: `/api/playback/speed/${streamId}/${speed}`
})
}
export function stop(deviceId, channelId, streamId) {
return request({
method: 'get',
url: '/api/playback/stop/' + deviceId + '/' + channelId + '/' + streamId
})
}

View File

@ -0,0 +1,85 @@
import request from '@/utils/request'
export function getPlan(id) {
return request({
method: 'get',
url: '/api/record/plan/get',
params: {
planId: id
}
})
}
export function addPlan(params) {
const { name, planList } = params
return request({
method: 'post',
url: '/api/record/plan/add',
data: {
name: name,
planItemList: planList
}
})
}
export function update(params) {
const { id, name, planList } = params
return request({
method: 'post',
url: '/api/record/plan/update',
data: {
id: id,
name: name,
planItemList: planList
}
})
}
export function queryList(params) {
const { page, count, query } = params
return request({
method: 'get',
url: `/api/record/plan/query`,
params: {
page: page,
count: count,
query: query
}
})
}
export function deletePlan(id) {
return request({
method: 'delete',
url: '/api/record/plan/delete',
params: {
planId: id
}
})
}
export function queryChannelList(params) {
const { page, count, channelType, query, online, planId , hasLink } = params
return request({
method: 'get',
url: `/api/record/plan/channel/list`,
params: {
page: page,
count: count,
query: query,
online: online,
channelType: channelType,
planId: planId,
hasLink: hasLink
}
})
}
export function linkPlan(data) {
return request({
method: 'post',
url: `/api/record/plan/link`,
data: data
})
}

96
wvpweb/src/api/region.js Normal file
View File

@ -0,0 +1,96 @@
import request from '@/utils/request'
// 行政区划API
export function getTreeList(params) {
const {query, parent, hasChannel} = params
return request({
method: 'get',
url: `/api/region/tree/list`,
params: {
query: query,
parent: parent,
hasChannel: hasChannel
}
})
}
export function deleteRegion(id) {
return request({
method: "delete",
url: `/api/region/delete`,
params: {
id: id,
}
})
}
export function description(civilCode) {
return request({
method: 'get',
url: `/api/region/description`,
params: {
civilCode: civilCode,
}
})
}
export function addByCivilCode(civilCode) {
return request({
method: 'get',
url: `/api/region/addByCivilCode`,
params: {
civilCode: civilCode,
}
})
}
export function queryChildListInBase(parent) {
return request({
method: 'get',
url: "/api/region/base/child/list",
params: {
parent: parent,
}
})
}
export function update(data) {
return request({
method: 'post',
url: "/api/region/update",
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: "/api/region/add",
data: data
})
}
export function queryPath(deviceId) {
return request({
method: 'get',
url: `/api/region/path`,
params: {
deviceId: deviceId,
}
})
}
export function queryTree(params) {
const { page, count, query } = params
return request({
method: 'get',
url: `/api/region/tree/query`,
params: {
query: query,
page: page,
count: count
}
})
}

11
wvpweb/src/api/role.js Normal file
View File

@ -0,0 +1,11 @@
import request from '@/utils/request'
// 云端录像API
export function getAll() {
return request({
method: 'get',
url: '/api/role/all'
})
}

130
wvpweb/src/api/server.js Normal file
View File

@ -0,0 +1,130 @@
import request from '@/utils/request'
// 服务API
export function getOnlineMediaServerList() {
return request({
method: 'get',
url: `/api/server/media_server/online/list`
})
}
export function getMediaServerList() {
return request({
method: 'get',
url: `/api/server/media_server/list`
})
}
export function getMediaServer(id) {
return request({
method: 'get',
url: `/api/server/media_server/one/` + id
})
}
export function checkMediaServer(params) {
const { ip, httpPort, secret, type } = params
return request({
method: 'get',
url: `/api/server/media_server/check`,
params: {
ip: ip,
port: httpPort,
secret: secret,
type: type
}
})
}
export function checkMediaServerRecord(params) {
const { ip, port } = params
return request({
method: 'get',
url: `/api/server/media_server/record/check`,
params: {
ip: ip,
port: port
}
})
}
export function saveMediaServer(formData) {
return request({
method: 'post',
url: `/api/server/media_server/save`,
data: formData
})
}
export function deleteMediaServer(id) {
return request({
method: 'delete',
url: `/api/server/media_server/delete`,
params: {
id: id
}
})
}
export function getSystemConfig() {
return request({
method: 'get',
url: `/api/server/system/configInfo`
})
}
export function getMediaInfo(params) {
const { app, stream, mediaServerId } = params
return request({
method: 'get',
url: `/api/server/media_server/media_info`,
params: {
app: app,
stream: stream,
mediaServerId: mediaServerId
}
})
}
export function getSystemInfo() {
return request({
method: 'get',
url: `/api/server/system/info`
})
}
export function getMediaServerLoad() {
return request({
method: 'get',
url: `/api/server/media_server/load`
})
}
export function getResourceInfo() {
return request({
method: 'get',
url: `/api/server/resource/info`
})
}
export function info() {
return request({
method: 'get',
url: `/api/server/info`
})
}
export function getMapConfig() {
return request({
method: 'get',
url: `/api/server/map/config`
})
}
export function getModelList() {
return request({
method: 'get',
url: `/api/server/map/model-icon/list`
})
}

View File

@ -0,0 +1,85 @@
import request from '@/utils/request'
// 拉流代理API
export function queryFfmpegCmdList(mediaServerId) {
return request({
method: 'get',
url: `/api/proxy/ffmpeg_cmd/list`,
params: {
mediaServerId: mediaServerId
}
})
}
export function save(data) {
return request({
method: 'post',
url: `/api/proxy/save`,
data: data
})
}
export function update(data) {
return request({
method: 'post',
url: `/api/proxy/update`,
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: `/api/proxy/add`,
data: data
})
}
export function queryList(params) {
const { page, count, query, pulling, mediaServerId } = params
return request({
method: 'get',
url: `/api/proxy/list`,
params: {
page: page,
count: count,
query: query,
pulling: pulling,
mediaServerId: mediaServerId
}
})
}
export function play(id) {
return request({
method: 'get',
url: `/api/proxy/start`,
params: {
id: id
}
})
}
export function stopPlay(id) {
return request({
method: 'get',
url: `/api/proxy/stop`,
params: {
id: id
}
})
}
export function remove(id) {
return request({
method: 'delete',
url: '/api/proxy/delete',
params: {
id: id
}
})
}

View File

@ -0,0 +1,80 @@
import request from '@/utils/request'
// 推流列表API
export function saveToGb(data) {
return request({
method: 'post',
url: `/api/push/save_to_gb`,
data: data
})
}
export function add(data) {
return request({
method: 'post',
url: `/api/push/add`,
data: data
})
}
export function update(data) {
return request({
method: 'post',
url: '/api/push/update',
data: data
})
}
export function queryList(params) {
const { page, count, query, pushing, mediaServerId } = params
return request({
method: 'get',
url: `/api/push/list`,
params: {
page: page,
count: count,
query: query,
pushing: pushing,
mediaServerId: mediaServerId
}
})
}
export function play(id) {
return request({
method: 'get',
url: '/api/push/start',
params: {
id: id
}
})
}
export function remove(id) {
return request({
method: 'post',
url: '/api/push/remove',
params: {
id: id
}
})
}
export function removeFormGb(data) {
return request({
method: 'delete',
url: '/api/push/remove_form_gb',
data: data
})
}
export function batchRemove(ids) {
return request({
method: 'delete',
url: '/api/push/batchRemove',
data: {
ids: ids
}
})
}

9
wvpweb/src/api/table.js Normal file
View File

@ -0,0 +1,9 @@
import request from '@/utils/request'
export function getList(params) {
return request({
url: '/vue-admin-template/table/list',
method: 'get',
params
})
}

91
wvpweb/src/api/user.js Normal file
View File

@ -0,0 +1,91 @@
import request from '@/utils/request'
export function login(params) {
return request({
url: '/api/user/login',
method: 'get',
params: params
})
}
export function logout() {
return request({
url: '/api/user/logout',
method: 'get'
})
}
export function getUserInfo() {
return request({
method: 'post',
url: '/api/user/userInfo'
})
}
export function changePushKey(params) {
const { pushKey, userId } = params
return request({
method: 'post',
url: '/api/user/changePushKey',
params: {
pushKey: pushKey,
userId: userId
}
})
}
export function queryList(params) {
const { page, count } = params
return request({
method: 'get',
url: `/api/user/users`,
params: {
page: page,
count: count
}
})
}
export function removeById(id) {
return request({
method: 'delete',
url: `/api/user/delete?id=${id}`
})
}
export function add(params) {
const { username, password, roleId } = params
return request({
method: 'post',
url: '/api/user/add',
params: {
username: username,
password: password,
roleId: roleId
}
})
}
export function changePassword(params) {
const { oldPassword, password } = params
return request({
method: 'post',
url: '/api/user/changePassword',
params: {
oldPassword: oldPassword,
password: password
}
})
}
export function changePasswordForAdmin(params) {
const { password, userId } = params
return request({
method: 'post',
url: '/api/user/changePasswordForAdmin',
params: {
password: password,
userId: userId
}
})
}

View File

@ -0,0 +1,69 @@
import request from '@/utils/request'
export function remark(params) {
const { id, remark } = params
return request({
method: 'post',
url: '/api/userApiKey/remark',
params: {
id: id,
remark: remark
}
})
}
export function queryList(params) {
const { page, count } = params
return request({
method: 'get',
url: `/api/userApiKey/userApiKeys`,
params: {
page: page,
count: count
}
})
}
export function enable(id) {
return request({
method: 'post',
url: `/api/userApiKey/enable?id=${id}`
})
}
export function disable(id) {
return request({
method: 'post',
url: `/api/userApiKey/disable?id=${id}`
})
}
export function reset(id) {
return request({
method: 'post',
url: `/api/userApiKey/reset?id=${id}`
})
}
export function remove(id) {
return request({
method: 'delete',
url: `/api/userApiKey/delete?id=${id}`
})
}
export function add(params) {
const { userId, app, enable, expiresAt, remark } = params
return request({
method: 'post',
url: '/api/userApiKey/add',
params: {
userId: userId,
app: app,
enable: enable,
expiresAt: expiresAt,
remark: remark
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
wvpweb/src/assets/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 KiB

BIN
wvpweb/src/assets/icons.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
wvpweb/src/assets/loading.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
wvpweb/src/assets/login-bg.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
wvpweb/src/assets/login-cloud.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
wvpweb/src/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
wvpweb/src/assets/play.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

BIN
wvpweb/src/assets/zlm-logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,78 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: '控制台' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === '控制台'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>

View File

@ -0,0 +1,44 @@
<template>
<div style="padding: 0 15px;" @click="toggleClick">
<svg
:class="{'is-active':isActive}"
class="hamburger"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64"
>
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
</svg>
</div>
</template>
<script>
export default {
name: 'Hamburger',
props: {
isActive: {
type: Boolean,
default: false
}
},
methods: {
toggleClick() {
this.$emit('toggleClick')
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
.hamburger.is-active {
transform: rotate(180deg);
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>

View File

@ -0,0 +1,77 @@
export default {
bind(el, binding, vnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const getStyle = (function() {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr]
}
})()
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomHeight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
// 获取到的值带px 正则匹配替换
let styL = getStyle(dragDom, 'left')
let styT = getStyle(dragDom, 'top')
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
} else {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let top = e.clientY - disY
// 边界处理
if (-(left) > minDragDomLeft) {
left = -minDragDomLeft
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-(top) > minDragDomTop) {
top = -minDragDomTop
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
// emit onDrag event
vnode.child.$emit('dragDialog')
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}

View File

@ -0,0 +1,13 @@
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag

View File

@ -0,0 +1,9 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1743481555402" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4475" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M104.64 0h128v632H337.28v128H232.64V1024h-128v-264H0v-128h104.64V0z m686.72 0h128v264H1024v128h-104.64V1024h-128V392H686.72v-128h104.64V0zM448 0h128v448h104.576v128H576v448H448V576H343.36V448H448z" p-id="4476"></path></svg>

After

Width:  |  Height:  |  Size: 533 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744253906048" class="icon" viewBox="0 0 1127 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2691" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M1074.12176 136.4v0.7l-0.5-0.3 0.5-0.4zM1020.82176 170v0.6l-0.5-0.3 0.5-0.3z m0 0" p-id="2692"></path><path d="M1127.52176 95.9v0.8l-0.6-0.3 0.6-0.5z m-59 37.2v0.7l-0.6-0.3 0.6-0.4z m0 0M645.52176 963.3c-72.2 0.1-131.6-56.9-134.3-129V690.9c2.7-72.2 62-129.3 134.3-129.3h7.3c10.6 0.2 20.6 4.9 27.7 13 9.1 10.7 11.1 25.8 5.1 38.5S666.92176 634 652.82176 634h-0.3c-16.1-1-31.9 4.4-44 15.2a60.444 60.444 0 0 0-20.3 41.9v142.8c1.3 32 27.7 57.1 59.7 57.1h244.6l2-20c1.1-31 26.6-55.7 57.7-55.6 7.5-0.1 15.1 1 22.3 3.3l73.6 25.7V680.9l-73.3 25.5c-6.6 2.4-13.7 3.7-20.8 3.7-24 0-45.7-14.1-55.6-36-2.5-6.1-3.9-12.6-4-19.3V636l-104.5-1.6c-19-1.9-33.4-18.3-32.7-37.4 0.8-19.2 16.5-34.3 35.7-34.7h99.7c40.1-1.1 74.3 28.8 78.5 68.7l70-24.3c6.9-2.3 14-3.5 21.1-3.5 32.9-1.1 60.7 24.1 62.8 56.9V864c0 7-1.3 14-4 20.5-6.1 14.8-17.8 26.7-32.7 32.7-15.1 6.3-31.9 6.9-47.4 1.6l-70-24.3c-1.3 18.2-9.6 35-23 47.3-14.9 13.7-34.7 21.4-55 21.4l-247.4 0.1z" p-id="2693"></path><path d="M297.42176 949.8C196.52176 949.1 103.12176 895.9 50.92176 809.4c-44.4-70.9-60.6-155.7-45.3-237.9 13.8-81.3 58.6-153.9 125-202.7 40.3-29.7 87.8-48.1 137.6-53.4 41.5-97.4 117.8-176 214.1-220.1 101-46.4 217-47.2 318.7-2.1 160.3 73.6 261.9 235.3 258.7 411.8 0.8 19.5-10.9 37.4-28.9 44.7-18.1 7.3-38.9 2.4-51.8-12.1-8.2-9.1-12.5-21.1-11.7-33.4 2.3-137.6-76.8-263.8-201.9-321.2-78.6-34.7-168.3-34-246.4 1.9C455.52176 214 403.12176 262.5 368.82176 323.3c72.9 19.7 135.5 66.6 175 131 14 22 8.6 51.2-12.1 66.9-7.7 5.5-17.1 8.5-26.6 8.7-15.8-0.1-30.5-8.4-38.6-21.9-29-47.3-76.1-80.6-130.2-92.5-53.4-11.2-109.1 1-152.9 33.4-46.1 33.8-77.2 84.3-86.7 140.6C85.92176 647 97.12176 706.1 128.12176 755.4c35.8 59.6 100 96.1 169.4 96.7h101.2c26 1.1 46.7 22.5 46.8 48.5 0.2 26.1-20.2 47.7-46.2 49.2h-102z" p-id="2694"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,4 @@
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg">
<path
d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1743060304116" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="45090" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M868 96H156c-33.1 0-60 26.9-60 60v712c0 33.1 26.9 60 60 60h712c33.1 0 60-26.9 60-60V156c0-33.1-26.9-60-60-60zM743.5 691.3c-20.9 20.3-51.3 38.1-91 53.5-39.7 15.4-80 23.1-120.7 23.1-51.8 0-96.9-10.9-135.4-32.6-38.5-21.7-67.4-52.8-86.8-93.2-19.4-40.4-29-84.4-29-131.9 0-51.6 10.8-97.4 32.4-137.5 21.6-40.1 53.2-70.8 94.9-92.2 31.7-16.4 71.3-24.7 118.5-24.7 61.5 0 109.5 12.9 144 38.7 34.6 25.8 56.8 61.4 66.7 106.9L637.8 420c-7-24.3-20.1-43.5-39.3-57.6-19.3-14.1-43.3-21.1-72.1-21.1-43.7 0-78.4 13.8-104.2 41.5-25.8 27.7-38.7 68.8-38.7 123.3 0 58.8 13.1 102.8 39.2 132.2 26.1 29.4 60.3 44.1 102.7 44.1 20.9 0 41.9-4.1 63-12.3 21-8.2 39.1-18.2 54.2-29.9v-62.8H528V494h215.5v197.3z" p-id="45091"></path></svg>

After

Width:  |  Height:  |  Size: 1015 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751337772774" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19666" id="mx_n_1751337772775" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M793.6 128a38.4 38.4 0 0 1 38.4 38.4v46.912h110.912a38.4 38.4 0 0 1 38.4 38.4V806.4a38.4 38.4 0 0 1-38.4 38.4L832 844.736v46.976a38.4 38.4 0 0 1-38.4 38.4H238.912a38.4 38.4 0 0 1-38.4-38.4V844.8L89.6 844.8a38.4 38.4 0 0 1-38.4-38.4V251.712a38.4 38.4 0 0 1 38.4-38.4h110.912V166.4a38.4 38.4 0 0 1 38.4-38.4H793.6z m-38.4 76.8H277.248v648.512H755.2V204.8zM200.448 290.112H128V768h72.512V290.112z m704 0H832V768h72.512V290.112z m-443.392 103.04l192 128a35.2 35.2 0 0 1 0 58.56l-192 128a35.2 35.2 0 0 1-54.72-29.312v-256c0-28.16 31.36-44.864 54.72-29.312z m15.68 94.976v124.48L570.112 550.4 476.8 488.128z" p-id="19667"></path></svg>

After

Width:  |  Height:  |  Size: 964 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751336642026" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4525" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M185.6 723.2v89.6h652.8v-89.6H185.6z m-6.4-64h665.6c31.7952 0 57.6 25.8048 57.6 57.6v102.4c0 31.7952-25.8048 57.6-57.6 57.6h-665.6A57.6 57.6 0 0 1 121.6 819.2v-102.4c0-31.7952 25.8048-57.6 57.6-57.6zM185.6 211.2v294.4h448v-294.4h-448zM179.2 147.2h460.8c31.7952 0 57.6 25.8048 57.6 57.6v307.2c0 31.7952-25.8048 57.6-57.6 57.6h-460.8A57.6 57.6 0 0 1 121.6 512V204.8c0-31.7952 25.8048-57.6 57.6-57.6z" p-id="4526"></path><path d="M697.6 415.4368l140.8 70.4V230.912l-140.8 70.4v114.0736z m121.4464-246.3232a57.6 57.6 0 0 1 83.3536 51.5072v275.5584a57.6 57.6 0 0 1-83.3536 51.5072l-185.4464-92.672V261.7856l185.4464-92.7232z" fill="#5A5A68" p-id="4527"></path></svg>

After

Width:  |  Height:  |  Size: 971 B

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

After

Width:  |  Height:  |  Size: 497 B

View File

@ -0,0 +1 @@
<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

After

Width:  |  Height:  |  Size: 944 B

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1743473861908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3656" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M863.008 384C916.576 384 960 341.024 960 288V160c0-53.024-43.424-96-96.992-96H160.992C107.424 64 64 106.976 64 160v128c0 53.024 43.424 96 96.992 96H320v128a32 32 0 0 0 32 32h288v96H160.992C107.424 640 64 682.976 64 736v128c0 53.024 43.424 96 96.992 96h702.016C916.576 960 960 917.024 960 864v-128c0-53.024-43.424-96-96.992-96H704v-128a32 32 0 0 0-32-32h-288v-96h479.008z m0 320c17.856 0 32.32 14.336 32.32 32v128c0 17.664-14.464 32-32.32 32H160.992c-17.856 0-32.32-14.336-32.32-32v-128c0-17.664 14.464-32 32.32-32h702.016zM128.672 288V160c0-17.664 14.464-32 32.32-32h702.016c17.856 0 32.32 14.336 32.32 32v128c0 17.664-14.464 32-32.32 32H160.992c-17.856 0-32.32-14.336-32.32-32z" p-id="3657"></path><path d="M320 832h384a32 32 0 0 0 0-64H320a32 32 0 0 0 0 64zM736 224a32 32 0 0 0-32-32H320a32 32 0 0 0 0 64h384a32 32 0 0 0 32-32z" p-id="3658"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744984386773" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2809" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M927.44064 56.064967A191.149846 191.149846 0 1 0 983.35197 191.303483a189.95516 189.95516 0 0 0-55.91133-135.238516zM792.202123 334.665867a143.362385 143.362385 0 1 1 143.362385-143.362384 143.362385 143.362385 0 0 1-143.362385 143.362384z" p-id="2810"></path><path d="M210.389779 1024h-11.230053a169.884426 169.884426 0 0 1-158.176498-169.884426V163.825692A169.406551 169.406551 0 0 1 210.389779 5.410257H515.990596a33.929098 33.929098 0 0 1 33.929097 33.929098 34.168035 34.168035 0 0 1-33.929097 33.929098H200.59335A101.548356 101.548356 0 0 0 108.602486 174.577871v689.334133A101.548356 101.548356 0 0 0 209.911905 955.902867h553.378804a101.787293 101.787293 0 0 0 92.229801-101.309418V480.656562a33.69016 33.69016 0 0 1 33.929098-33.929097 33.929098 33.929098 0 0 1 33.929097 33.929097v384.689066a169.645488 169.645488 0 0 1-169.406551 158.654372z" p-id="2811"></path><path d="M293.539962 565.240369h376.565197v57.822829H293.539962zM294.495712 405.869185h202.857774v57.822829h-202.857774zM770.219891 88.082566h28.672477V186.524737h-28.672477z" p-id="2812"></path><path d="M770.219891 185.091113h134.521704v28.672477h-134.521704z" fill="#040000" p-id="2813"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746918194106" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9149" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M893.612371 819.374576l-21.278629-614.998839c0-55.031361-47.635927-99.639325-106.394169-99.639325L255.245312 104.736413c-58.759265 0-106.393145 44.608987-106.393145 99.639325L127.572514 819.374576l73.747631 0c-0.535189 2.812045-0.873903 5.697769-0.873903 8.667404l0 20.224624c0 25.529443 20.695345 46.225811 46.225811 46.225811l66.451458 0c25.532513 0 46.227858-20.697391 46.227858-46.225811L359.351368 828.04198c0-2.968611-0.338714-5.854335-0.873903-8.667404l304.232003 0c-0.535189 2.812045-0.873903 5.697769-0.873903 8.667404l0 20.224624c0 25.529443 20.696368 46.225811 46.227858 46.225811l66.451458 0c25.530466 0 46.227858-20.697391 46.227858-46.225811L820.742736 828.04198c0-2.968611-0.338714-5.854335-0.873903-8.667404L893.612371 819.374576zM258.868839 723.007785c-32.264844 0-58.422597-26.157753-58.422597-58.424644 0-32.266891 26.157753-58.424644 58.422597-58.424644 32.268938 0 58.424644 26.157753 58.424644 58.424644C317.293483 696.850032 291.137777 723.007785 258.868839 723.007785zM217.490429 510.921435l7.91732-252.475222c0-55.682183 20.277836-77.706803 71.538313-77.706803l427.009304 0c51.260477 0 71.538313 22.024619 71.538313 77.706803l8.201799 252.475222L217.490429 510.921435zM762.316046 723.007785c-32.266891 0-58.424644-26.157753-58.424644-58.424644 0-32.266891 26.157753-58.424644 58.424644-58.424644 32.266891 0 58.424644 26.157753 58.424644 58.424644C820.74069 696.850032 794.582937 723.007785 762.316046 723.007785z" p-id="9150"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Some files were not shown because too many files have changed in this diff Show More