Compare commits

..

6 Commits

Author SHA1 Message Date
han a5ce121f31 注释2
1 year ago
han c38dc8d608 注释2
1 year ago
han a0df6af760 注释1
1 year ago
han 066426ca36 87uh87uy0
1 year ago
han ab89dcf9b3 add readme
1 year ago
p9tnomuae 3926f76968 accept pr
1 year ago

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/yolov8-master.iml" filepath="$PROJECT_DIR$/.idea/yolov8-master.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

@ -1,8 +1,13 @@
<template>
<!-- 定义一个名为app-main的section标签这通常是页面主要内容的容器 -->
<section class="app-main">
<!-- router-view用于渲染路由对应的组件通过v-slot可以获取到组件以及当前路由等相关信息 -->
<router-view v-slot="{ Component, route }">
<!-- 使用Vue的过渡效果名称为fade-transform模式是out-in用于实现组件切换时的过渡动画效果 -->
<transition name="fade-transform" mode="out-in">
<!-- keep-alive标签用于缓存组件避免组件在切换时重复创建和销毁提高性能 -->
<keep-alive>
<!-- 通过动态组件的方式渲染Component对应的组件以route.fullPath作为组件的key便于Vue进行区分和更新 -->
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</transition>
@ -11,37 +16,41 @@
</template>
<script setup lang="ts">
// JavaScript
</script>
<style lang="scss" scoped>
.app-main {
/* 50= navbar 50 */
/* 计算页面主体的最小高度通过100vh视口高度减去50px可能是导航栏之类的固定高度占用的空间来确定确保内容区域高度自适应同时避免滚动条出现异常等情况 */
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}
/* 当存在fixed-header类的元素时给app-main元素添加顶部内边距50px可能是为了避免内容被fixed-header遮挡等布局相关的调整 */
.fixed-header+.app-main {
padding-top: 50px;
}
.hasTagsView {
.app-main {
/* 84 = navbar + tags-view = 50 + 34 */
.app-main {
/* 同样是计算页面主体最小高度这里减去的84px可能是导航栏加上其他视图比如标签栏之类的高度总和为84px占用的空间根据不同的布局情况来准确设置内容区域高度 */
min-height: calc(100vh - 84px);
}
.fixed-header+.app-main {
.fixed-header+.app-main {
/* 与上面类似当存在fixed-header且有hasTagsView这个类相关的布局情况时给app-main添加顶部内边距84px保证内容显示位置正确 */
padding-top: 84px;
}
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
// el-dialogElement UICSSBug
// el-popup-parent--hidden.fixed-header17px
.el-popup-parent--hidden {
.fixed-header {
.fixed-header {
padding-right: 17px;
}
}

@ -1,42 +1,51 @@
<template>
<!-- 定义一个类名为navbar的div作为导航栏的外层容器 -->
<div class="navbar">
<!-- 折叠按钮 -->
<!-- 折叠按钮组件类名为hamburger-container可能用于控制导航栏或侧边栏等的展开与折叠功能 -->
<hamburger class="hamburger-container"></hamburger>
<!-- 面包屑 -->
<!-- 面包屑组件用于展示页面的层级结构路径类名为breadcrumb-container -->
<breadcrumb class="breadcrumb-container"></breadcrumb>
<div class="right-menu">
<template v-if="device !== 'mobile'">
<!-- 系统首页 -->
<!-- 根据设备类型进行条件渲染如果设备不是移动端可能是PC端等则显示以下内容 -->
<template v-if="device!== 'mobile'">
<!-- 使用el-tooltip组件为以下元素添加提示信息提示内容为"系统首页"提示效果为深色dark显示位置在底部bottom -->
<el-tooltip content="系统首页" effect="dark" placement="bottom">
<!-- 定义一个类名为right-menu-item且带有hover-effect类的div用于实现鼠标悬停等交互效果 -->
<div class="right-menu-item hover-effect">
<!-- svg-icon组件绑定点击事件openHome用于显示特定图标这里图标类名为home尺寸为1.2rem可能点击后跳转到系统首页 -->
<svg-icon @click="openHome" icon-class="home" size="1.2rem" />
</div>
</el-tooltip>
<!-- 修改密码 -->
<!-- 类似上面的el-tooltip结构用于显示"修改密码"的提示信息内部包含password组件可能用于打开修改密码的相关界面 -->
<el-tooltip content="修改密码" effect="dark" placement="bottom">
<password class="right-menu-item hover-effect"></password>
</el-tooltip>
<!-- 全屏 -->
<!-- screenfull组件类名为right-menu-item且带有hover-effect类可能用于实现页面全屏功能 -->
<screenfull class="right-menu-item hover-effect"></screenfull>
<!-- 布局大小 -->
<!-- 以下代码被注释掉了原本可能用于显示"布局大小"的提示信息内部包含size-select组件也许是用于调整页面布局大小相关操作 -->
<!-- <el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select class="right-menu-item hover-effect" />
</el-tooltip> -->
</template>
<!-- el-dropdown组件用于创建下拉菜单绑定了command事件处理函数handleCommand类名为avatar-container和right-menu-item以及hover-effect触发方式为点击click -->
<el-dropdown @command="handleCommand" class="avatar-container right-menu-item hover-effect" trigger="click">
<!-- 头像 -->
<!-- 内部包含一个类名为avatar-wrapper的div用于包裹头像相关元素 -->
<div class="avatar-wrapper">
<!-- 展示用户头像通过绑定:src属性动态获取用户头像的地址来自user.avatar类名为user-avatar -->
<img :src="user.avatar" class="user-avatar" />
<!-- el-icon组件内部使用caret-bottom组件用于显示一个向下的箭头图标可能用于指示下拉菜单的展开方向 -->
<el-icon class="el-icon-caret-bottom">
<caret-bottom />
</el-icon>
</div>
<!-- 选项 -->
<!-- 使用template并通过#dropdown插槽来定义下拉菜单的具体内容 -->
<template #dropdown>
<el-dropdown-menu>
<!-- el-dropdown-item组件定义一个可点击的下拉菜单项绑定命令command"setLayout"点击后可能执行相关布局设置操作 -->
<el-dropdown-item command="setLayout">
<span>布局设置</span>
</el-dropdown-item>
<!-- 类似上面的el-dropdown-item绑定命令为"logout"点击后可能执行退出登录操作并且添加了分割线divided样式 -->
<el-dropdown-item divided command="logout">
<span>退出登录</span>
</el-dropdown-item>
@ -48,79 +57,108 @@
</template>
<script setup lang="ts">
import breadcrumb from "@/components/Breadcrumb/index.vue";
import hamburger from "@/components/Hamburger/index.vue";
import password from "@/components/Password/index.vue";
import Screenfull from '@/components/Screenfull/index.vue';
import SizeSelect from '@/components/SizeSelect/index.vue';
import useStore from "@/store";
import { messageConfirm } from "@/utils/modal";
import { computed } from "vue";
const { app, user } = useStore();
const device = computed(() => app.device);
const openHome = () => {
// console.log(user.avatar)
window.open("http://127.0.0.1:8090");
};
const handleCommand = (command: string) => {
switch (command) {
case "setLayout":
setLayout();
break;
case "logout":
logout();
break;
default:
break;
}
};
const logout = () => {
messageConfirm("确定注销并退出系统吗?").then(() => {
user.LogOut().then(() => {
location.href = "/login";
});
}).catch(() => { });
};
const emits = defineEmits(['setLayout']);
const setLayout = () => {
emits('setLayout');
};
//
import breadcrumb from "@/components/Breadcrumb/index.vue";
//
import hamburger from "@/components/Hamburger/index.vue";
//
import password from "@/components/Password/index.vue";
//
import Screenfull from '@/components/Screenfull/index.vue';
//
import SizeSelect from '@/components/SizeSelect/index.vue';
// Vuexstore
import useStore from "@/store";
//
import { messageConfirm } from "@/utils/modal";
// Vuecomputed
import { computed } from "vue";
// storeappuser
const { app, user } = useStore();
// deviceapp
const device = computed(() => app.device);
// openHomehttp://127.0.0.1:8090
const openHome = () => {
// console.log(user.avatar)
window.open("http://127.0.0.1:8090");
};
// handleCommandel-dropdowncommand
const handleCommand = (command: string) => {
switch (command) {
case "setLayout":
setLayout();
break;
case "logout":
logout();
break;
default:
break;
}
};
// logout退
// 退userLogOut/login
const logout = () => {
messageConfirm("确定注销并退出系统吗?").then(() => {
user.LogOut().then(() => {
location.href = "/login";
});
}).catch(() => { });
};
// emitsemit'setLayout'便
const emits = defineEmits(['setLayout']);
// setLayout'setLayout'
const setLayout = () => {
emits('setLayout');
};
</script>
<style lang="scss" scoped>
.navbar {
// 50px使flex--el-bg-color
height: 50px;
overflow: hidden;
position: relative;
display: flex;
background-color: var(--el-bg-color);
.hamburger-container {
.hamburger-container {
// 100%cursor: pointer
line-height: 46px;
height: 100%;
float: left;
cursor: pointer;
&:hover {
// 使rgba
background: rgba(0, 0, 0, 0.025);
}
}
.breadcrumb-container {
.breadcrumb-container {
//
float: left;
}
.right-menu {
.right-menu {
// margin-leftauto100%50px
margin-left: auto;
height: 100%;
line-height: 50px;
&:focus {
//
outline: none;
}
.right-menu-item {
.right-menu-item {
// inline-block
display: inline-block;
padding: 0 8px;
height: 100%;
@ -129,30 +167,36 @@ const setLayout = () => {
vertical-align: text-bottom;
&.hover-effect {
// 0.3
cursor: pointer;
transition: background 0.3s;
&:hover {
// 使
background: rgba(0, 0, 0, 0.025);
}
}
}
.avatar-container {
.avatar-container {
// 30px
margin-right: 30px;
.avatar-wrapper {
.avatar-wrapper {
// 5px
margin-top: 5px;
position: relative;
.user-avatar {
.user-avatar {
// 使
cursor: pointer;
width: 40px;
height: 40px;
border-radius: 50%;
}
.el-icon-caret-bottom {
.el-icon-caret-bottom {
//
cursor: pointer;
position: absolute;
right: -20px;
@ -163,4 +207,4 @@ const setLayout = () => {
}
}
}
</style>
</style>

@ -1,24 +1,33 @@
<template>
<!-- 使用动态组件根据 type 变量渲染不同的组件 -->
<component :is="type" v-bind="linkProps()">
<!-- 插槽用于在该组件中插入内容 -->
<slot />
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
// propsto
const props = defineProps({
to: {
type: [String, Object],
required: true
}
});
//
const type = computed(() => {
// 'router-link'
return 'router-link'
});
//
const linkProps = () => {
// to
return {
to: props.to
to: props.to // to router-link
}
}
</script>

@ -1,11 +1,18 @@
<template>
<!-- 侧边栏logo容器根据 isCollapse 状态动态添加 collapse -->
<div class="sidebar-logo-container" :class="{ collapse: isCollapse }">
<!-- isCollapse true 时渲染的链接和 logo -->
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<!-- 如果 logo 存在则显示 logo 图片 -->
<img v-if="logo" :src="logo" class="sidebar-logo" />
<!-- 如果 logo 不存在则显示默认标题 -->
<h1 v-else class="sidebar-title">Pan-MTAS系统</h1>
</router-link>
<!-- isCollapse false 时渲染的链接和 logo -->
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<!-- 如果 logo 存在则显示 logo 图片 -->
<img v-if="logo" :src="logo" class="sidebar-logo" />
<!-- 显示扩展时的标题 -->
<h1 class="sidebar-title">MTAS系统</h1>
</router-link>
</div>
@ -14,6 +21,7 @@
<script setup lang="ts">
import { reactive, toRefs } from "vue";
// propscollapse
const props = defineProps({
collapse: {
type: Boolean,
@ -21,49 +29,51 @@ const props = defineProps({
},
});
// isCollapse logo
const state = reactive({
isCollapse: props.collapse,
logo: new URL(`../../../assets/logo.png`, import.meta.url).href,
isCollapse: props.collapse, // props
logo: new URL(`../../../assets/logo.png`, import.meta.url).href, // logoURL
});
// 使 toRefs 便使
const { logo, isCollapse } = toRefs(state);
</script>
<style lang="scss" scoped>
.sidebar-logo-container {
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
overflow: hidden;
position: relative; /* 使容器相对定位 */
width: 100%; /* 容器宽度100% */
height: 50px; /* 容器高度 */
line-height: 50px; /* 行高与高度相同,以垂直居中内容 */
text-align: center; /* 文本居中对齐 */
overflow: hidden; /* 隐藏溢出内容 */
& .sidebar-logo-link {
height: 100%;
width: 100%;
height: 100%; /* 链接高度100% */
width: 100%; /* 链接宽度100% */
& .sidebar-logo {
width: 20px;
height: 20px;
vertical-align: middle;
width: 20px; /* logo宽度 */
height: 20px; /* logo高度 */
vertical-align: middle; /* 垂直对齐 */
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
margin-left: 12px;
display: inline-block; /* 使标题为块级元素 */
margin: 0; /* 去掉默认外边距 */
color: #fff; /* 字体颜色为白色 */
font-weight: 600; /* 字体加粗 */
line-height: 50px; /* 行高与容器高度相同,以垂直居中 */
font-size: 14px; /* 字体大小 */
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; /* 字体系列 */
vertical-align: middle; /* 垂直对齐 */
margin-left: 12px; /* 左边距 */
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
margin-right: 0px; /* 当收起时logo右边距为0 */
}
}
}

@ -1,12 +1,15 @@
<template>
<!-- 根据showLogo这个计算属性的值来动态添加或移除'has-logo'类名用于控制是否显示带有logo相关样式的布局 -->
<div :class="{ 'has-logo': showLogo }">
<!-- 网站Logo -->
<!-- 当showLogo为真时显示网站Logo组件同时传递collapse属性给Logo组件用于告知其是否处于折叠状态 -->
<logo v-if="showLogo" :collapse="isCollapse" />
<!-- 侧边栏 -->
<!-- 使用el-scrollbar组件包裹el-menu组件侧边栏添加滚动条功能wrap-class用于指定滚动条的外层包装类名 -->
<el-scrollbar wrap-class="scrollbar-wrapper">
<!-- el-menu组件用于构建侧边栏菜单以下是配置各个属性 -->
<el-menu :default-active="activeMenu" :unique-opened="true" :collapse="isCollapse" :collapse-transition="false"
:background-color="variables.menuBg" :text-color="variables.menuText"
:active-text-color="variables.menuActiveText">
<!-- 使用v-for指令循环遍历routes数组计算属性获取到的路由数据创建多个SidebarItem组件每个组件代表侧边栏的一个菜单项传递相应的属性 -->
<sidebar-item v-for="route in routes" :item="route" :key="route.path" :base-path="route.path" />
</el-menu>
</el-scrollbar>
@ -14,54 +17,86 @@
</template>
<script setup lang="ts">
import variables from '@/assets/styles/variables.module.scss';
import useStore from "@/store";
import { computed } from "vue";
import { useRoute } from 'vue-router';
import Logo from './Logo.vue';
import SidebarItem from './SidebarItem.vue';
const { app, setting, permission } = useStore();
const route = useRoute();
const isCollapse = computed(() => app.isCollapse);
const showLogo = computed(() => setting.sidebarLogo);
// const routes = computed(() => permission.routes);
const activeMenu = computed(() => route.path);
//
import variables from '@/assets/styles/variables.module.scss';
// Vuexstore
import useStore from "@/store";
// Vuecomputed
import { computed } from "vue";
// Vue Router
import { useRoute } from 'vue-router';
// LogoLogo
import Logo from './Logo.vue';
// SidebarItem
import SidebarItem from './SidebarItem.vue';
const fakeRoutes = [
{
path: '/index',
meta: { title: '系统首页', icon: 'archives' },
},
{
path: '',
meta: { title: '系统管理', icon: 'system' },
children: [
{
path: '/alarm',
meta: { title: '警告信息', icon: 'dashboard' }
},
// {
// path: '/monitor',
// meta: { title: '', icon: 'dashboard' }
// },
{
path: '/setting',
meta: { title: '监控配置', icon: 'edit' }
},
{
path: '/manager',
meta: { title: '监控管理', icon: 'example' }
},
{
path: '/user',
meta: { title: '系统人员', icon: 'user' }
}
]
},
// ...
];
// storeappsettingpermission
const { app, setting, permission } = useStore();
//
const route = useRoute();
const routes = computed(() => fakeRoutes);
// isCollapseapp.isCollapse便
const isCollapse = computed(() => app.isCollapse);
// showLogosetting.sidebarLogoLogo
const showLogo = computed(() => setting.sidebarLogo);
// permission使使
// const routes = computed(() => permission.routes);
// activeMenu
const activeMenu = computed(() => route.path);
// pathmetatitleiconchildren
const fakeRoutes = [
{
path: '/index',
meta: { title: '系统首页', icon: 'archives' },
},
{
path: '',
meta: { title: '系统管理', icon: 'system' },
children: [
{
path: '/alarm',
meta: { title: '警告信息', icon: 'dashboard' }
},
// {
// path: '/monitor',
// meta: { title: '', icon: 'dashboard' }
// },
{
path: '/setting',
meta: { title: '监控配置', icon: 'edit' }
},
{
path: '/manager',
meta: { title: '监控管理', icon: 'example' }
},
{
path: '/user',
meta: { title: '系统人员', icon: 'user' }
}
]
},
// ...
];
// routes
const routes = computed(() => fakeRoutes);
// SidebarItem
//
const handleMenuItemClick = (route: any) => {
// app.isCollapse
if (route.children && isCollapse.value) {
app.isCollapse = false;
}
// 使Vue Routerpush
router.push(route.path);
};
</script>
<style scoped></style>
<style scoped>
/* 这里可以添加针对当前组件的样式规则,如果有特定的样式需求,比如对侧边栏的布局、滚动条样式等进行更精细的调整 */
</style>

@ -1,109 +1,142 @@
<template>
<!-- 根据 `classObj` 计算属性动态绑定类名同时添加固定的 `app-wrapper` 类名用于包裹整个页面的主要结构 -->
<div :class="classObj" class="app-wrapper">
<div v-if="(device === 'mobile' && !app.isCollapse)" class="drawer-bg" @click="handleClickOutside" />
<!-- 侧边栏 -->
<!-- 当设备为移动端`device ==='mobile'`且侧边栏未折叠`!app.isCollapse`时显示这个覆盖层点击它可以触发关闭侧边栏的操作通过 `handleClickOutside` 方法用于实现点击侧边栏外部区域关闭侧边栏的功能 -->
<div v-if="(device ==='mobile' &&!app.isCollapse)" class="drawer-bg" @click="handleClickOutside" />
<!-- 引入侧边栏组件 `SideBar`并添加 `sidebar-container` 类名用于页面侧边栏的展示 -->
<SideBar class="sidebar-container"></SideBar>
<!-- 根据 `needTagView` 计算属性动态添加 `hasTagsView` 类名同时添加 `main-container` 类名用于包裹页面主体内容相关的部分如导航栏标签栏主要内容区域等 -->
<div :class="{ hasTagsView: needTagView }" class="main-container">
<!-- 根据 `fixedHeader` 计算属性动态添加 `fixed-header` 类名用于设置页面头部可能包含导航栏等是否固定定位 -->
<div :class="{ 'fixed-header': fixedHeader }">
<!-- 导航栏 -->
<!-- 引入导航栏组件 `NavBar`并监听它发出的 `setLayout` 事件当事件触发时调用 `setLayout` 方法进行相应布局设置操作 -->
<NavBar @setLayout="setLayout"></NavBar>
<!-- 历史标签栏 -->
<!-- 当需要显示历史标签栏 `needTagView` 计算属性决定展示 `TagView` 组件用于展示页面访问历史等相关标签 -->
<TagView v-if="needTagView"></TagView>
</div>
<!-- 引入主要内容展示组件 `AppMain`用于显示页面核心的业务内容 -->
<AppMain></AppMain>
<!-- 设置 -->
<!-- 引入设置组件 `Settings`并通过 `ref` 创建一个引用 `settingRef`方便后续在代码中操作该组件例如调用组件内的方法等 -->
<Settings ref="settingRef"></Settings>
</div>
</div>
</template>
<script setup lang="ts">
import Settings from "@/components/Settings/index.vue";
import TagView from "@/components/TagView/index.vue";
import useStore from "@/store";
import { useWindowSize } from "@vueuse/core";
import { computed, ref, watchEffect } from "vue";
import AppMain from "./components/AppMain/index.vue";
import NavBar from "./components/NavBar/index.vue";
import SideBar from "./components/SideBar/index.vue";
// `Settings`
import Settings from "@/components/Settings/index.vue";
// `TagView`访
import TagView from "@/components/TagView/index.vue";
// Vuex `useStore` Vuex
import useStore from "@/store";
// `@vueuse/core` `useWindowSize`
import { useWindowSize } from "@vueuse/core";
// `vue` `computed``ref``watchEffect`
import { computed, ref, watchEffect } from "vue";
// `AppMain`
import AppMain from "./components/AppMain/index.vue";
// `NavBar`
import NavBar from "./components/NavBar/index.vue";
// `SideBar`
import SideBar from "./components/SideBar/index.vue";
const { app, setting } = useStore();
const { width } = useWindowSize();
const WIDTH = 992;
const settingRef = ref();
// Vuex `store` `app` `setting` `app` `setting`
const { app, setting } = useStore();
// `width`
const { width } = useWindowSize();
// `WIDTH` `992`
const WIDTH = 992;
// `settingRef` `Settings` 便
const settingRef = ref();
const device = computed(() => app.device);
const needTagView = computed(() => setting.tagView);
const fixedHeader = computed(() => setting.fixedHeader);
const classObj = computed(() => ({
hideSidebar: app.isCollapse,
openSidebar: !app.isCollapse,
mobile: device.value === "mobile",
}));
// `device` `app` `device`
const device = computed(() => app.device);
// `needTagView` `setting` `tagView`
const needTagView = computed(() => setting.tagView);
// `fixedHeader` `setting` `fixedHeader`
const fixedHeader = computed(() => setting.fixedHeader);
// `classObj` `app` `div`
const classObj = computed(() => ({
hideSidebar: app.isCollapse,
openSidebar:!app.isCollapse,
mobile: device.value === "mobile",
}));
watchEffect(() => {
if (width.value - 1 < WIDTH) {
app.toggleDevice("mobile");
// 使 `watchEffect` `width`
// `1` `WIDTH` `mobile` `desktop`
watchEffect(() => {
if (width.value - 1 < WIDTH) {
app.toggleDevice("mobile");
app.changeCollapse(true);
} else {
app.toggleDevice("desktop");
}
});
// `handleClickOutside` `app` `changeCollapse`
const handleClickOutside = () => {
app.changeCollapse(true);
} else {
app.toggleDevice("desktop");
}
});
const handleClickOutside = () => {
app.changeCollapse(true);
}
const setLayout = () => {
settingRef.value.openSetting();
}
// `setLayout` `NavBar` `setLayout` `settingRef` `Settings` `openSetting`
const setLayout = () => {
settingRef.value.openSetting();
}
</script>
<style lang="scss" scoped>
@import "@/assets/styles/mixin.scss";
@import "@/assets/styles/variables.module.scss";
// mixin便使
@import "@/assets/styles/mixin.scss";
// 便使
@import "@/assets/styles/variables.module.scss";
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
// 使mixin `clearfix` `mixin.scss` `100%`使
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar {
position: fixed;
top: 0;
// `mobile.openSidebar`
&.mobile.openSidebar {
position: fixed;
top: 0;
}
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
// `0.3`使 `100%``z-index` `999`
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 40;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
// `z-index` `40` `$sideBarWidth` 使
position: fixed;
top: 0;
right: 0;
z-index: 40;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - 64px);
}
// `.hideSidebar` `64px`
.hideSidebar.fixed-header {
width: calc(100% - 64px);
}
.sidebarHide .fixed-header {
width: 100%;
}
// `sidebarHide` `100%`使
.sidebarHide.fixed-header {
width: 100%;
}
.mobile .fixed-header {
width: 100%;
}
</style>
// `100%`
.mobile.fixed-header {
width: 100%;
}
</style>

@ -1,83 +1,136 @@
// 导入布局组件Layout通常作为页面整体布局的基础框架其他页面组件可能会嵌套在其中进行展示
import Layout from "@/layouts/index.vue";
// 从'vue-router'库中导入创建路由实例、创建Web历史模式以及定义路由记录类型所需的函数和类型
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
// 定义一个常量数组constantRoutes其元素类型为RouteRecordRaw路由记录类型用于配置一些固定的、不会动态变化的路由信息
export const constantRoutes: RouteRecordRaw[] = [
{
path: "/redirect",
component: Layout,
meta: { hidden: true },
children: [
{
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
],
},
{
path: "/login",
name: "登录",
component: () => import("@/views/login/index.vue"),
meta: {
hidden: true,
// 配置一个名为'redirect'的路由
{
path: "/redirect",
// 使用Layout组件作为该路由的布局组件意味着这个路由下的页面内容会展示在Layout组件所定义的布局结构内
component: Layout,
// 设置meta元数据其中'hidden'属性为true表示这个路由在菜单等展示场景中通常是隐藏的不直接展示给用户
meta: { hidden: true },
children: [
// 配置'redirect'路由的子路由,路径使用了动态参数':path(.*)',表示可以匹配任意路径
// 当匹配到相应路径时,会加载并展示'@/views/redirect/index.vue'这个组件
{
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
],
},
},
{
path: "/:pathMatch(.*)*",
component: () => import("@/views/error/404.vue"),
meta: {
hidden: true,
// 配置名为'login'的路由,用于用户登录页面
{
path: "/login",
// 给路由设置一个名称,方便后续在代码中通过名称来引用这个路由,这里设置为中文'登录'(实际中更建议使用英文命名规范)
name: "登录",
// 通过动态导入的方式加载'@/views/login/index.vue'组件作为该路由对应的页面内容
component: () => import("@/views/login/index.vue"),
meta: {
// 设置'hidden'属性为true同样表示该路由在常规菜单等展示场景中是隐藏的比如可能不会出现在侧边栏菜单里
hidden: true,
},
},
// 配置一个通配符路由,用于处理所有未匹配到的路径
{
path: "/:pathMatch(.*)*",
// 当访问的路径没有匹配到前面定义的任何路由时,会加载并展示'@/views/error/404.vue'组件通常用于显示404页面提示用户访问的页面不存在
component: () => import("@/views/error/404.vue"),
meta: {
hidden: true,
},
},
// 配置根路由(路径为'/'),这是应用的默认入口路由
{
path: "/",
// 使用Layout组件作为根路由的布局组件根路由下的其他子路由页面都会展示在这个布局框架内
component: Layout,
// 设置重定向,当访问根路由时,会自动重定向到'/index'路由
redirect: "/index",
children: [
// 配置'/index'子路由,这可能是应用的首页路由
{
path: "/index",
// 通过动态导入加载'@/views/home/index.vue'组件作为首页的页面内容
component: () => import("@/views/home/index.vue"),
// 给路由设置名称为'Index',方便后续引用
name: "Index",
meta: {
// 设置页面标题为'首页',图标为'dashboard'(可能用于菜单中展示对应的图标),'affix'属性为true表示这个路由对应的页面在某些情况下比如标签栏等会固定显示不随路由切换而轻易消失
title: "首页",
icon: "dashboard",
affix: true,
},
},
// 配置'/monitor'子路由,用于展示监控面板相关页面
{
path: "/monitor",
component: () => import("@/views/system/monitorPanel/index.vue"),
name: "monitor",
meta: {
title: "监控面板",
icon: "dashboard",
affix: true,
},
},
// 配置'/manager'子路由,用于展示监控管理相关页面
{
path: "/manager",
component: () => import("@/views/system/streamingManager/index.vue"),
name: "manager",
meta: {
title: "监控管理",
icon: "dashboard",
affix: true,
},
},
// 配置'/setting'子路由,用于展示监控配置相关页面
{
path: "/setting",
component: () => import("@/views/system/streamingSetting/index.vue"),
name: "setting",
meta: {
title: "监控配置",
icon: "dashboard",
affix: true,
},
},
// 配置'/alarm'子路由,用于展示警告信息相关页面
{
path: "/alarm",
component: () => import("@/views/system/alarm/index.vue"),
name: "alarm",
meta: {
title: "警告信息",
icon: "dashboard",
affix: true,
},
},
// 配置'/user'子路由,用于展示用户管理相关页面
{
path: "/user",
component: () => import("@/views/system/user/index.vue"),
name: "user",
meta: {
title: "用户管理",
icon: "dashboard",
affix: true,
},
},
// 可以在这里继续添加其他的子路由配置,按照同样的格式即可
],
},
},
{
path: "/",
component: Layout,
redirect: "/index",
children: [
{
path: "/index",
component: () => import("@/views/home/index.vue"),
name: "Index",
meta: { title: "首页", icon: "dashboard", affix: true },
},
{
path: "/monitor",
component: () => import("@/views/system/monitorPanel/index.vue"),
name: "monitor",
meta: { title: "监控面板", icon: "dashboard", affix: true },
},
{
path: "/manager",
component: () => import("@/views/system/streamingManager/index.vue"),
name: "manager",
meta: { title: "监控管理", icon: "dashboard", affix: true },
},
{
path: "/setting",
component: () => import("@/views/system/streamingSetting/index.vue"),
name: "setting",
meta: { title: "监控配置", icon: "dashboard", affix: true },
},
{
path: "/alarm",
component: () => import("@/views/system/alarm/index.vue"),
name: "alarm",
meta: { title: "警告信息", icon: "dashboard", affix: true },
},
{
path: "/user",
component: () => import("@/views/system/user/index.vue"),
name: "user",
meta: { title: "用户管理", icon: "dashboard", affix: true },
},
],
},
];
// 创建一个Vue Router实例用于管理应用的路由系统
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
// 使用createWebHistory创建Web历史模式这种模式下的路由路径会以正常的URL路径形式展示例如http://example.com/about而不是类似哈希模式#/about的形式
history: createWebHistory(),
// 将前面配置好的constantRoutes数组作为路由实例的路由配置信息即告诉路由实例有哪些路由可以进行导航和匹配
routes: constantRoutes,
});
export default router;
// 将创建好的路由实例导出方便在Vue应用的入口文件或者其他需要使用路由的地方进行导入和使用
export default router;

@ -1,15 +1,27 @@
// 导入应用相关的状态管理模块store通常里面包含了如应用的设备类型、侧边栏折叠状态等与应用整体状态相关的逻辑和数据
import useAppStore from "./modules/app";
// 导入标签相关的状态管理模块,可能用于管理页面标签(比如历史访问标签等)相关的数据和操作逻辑
import useTagStore from "./modules/tag";
// 导入设置相关的状态管理模块,涉及应用各种设置项(例如是否显示某些界面元素、布局设置等)的数据和操作逻辑
import useSettingStore from "./modules/setting";
// 导入权限相关的状态管理模块,用于处理用户权限相关的数据以及权限验证、路由权限控制等操作逻辑
import usePermissionStore from "./modules/permission";
// 导入用户相关的状态管理模块,包含用户信息(如用户名、登录状态、用户角色等)的管理以及与用户相关操作(如登录、注销等)的逻辑
import useUserStore from "./modules/user";
// 定义一个名为useStore的函数该函数的作用是将各个模块的store进行整合并返回一个包含多个属性的对象
const useStore = () => ({
tag: useTagStore(),
app: useAppStore(),
setting: useSettingStore(),
user: useUserStore(),
permission: usePermissionStore(),
// 将标签相关的store作为返回对象的'tag'属性,方便通过这个属性去访问和操作标签相关的状态数据以及调用对应的方法
tag: useTagStore(),
// 将应用相关的store作为返回对象的'app'属性,用于获取和操作应用整体相关的状态信息等
app: useAppStore(),
// 把设置相关的store作为'resetting'属性,以此来操作应用的各项设置内容
setting: useSettingStore(),
// 将用户相关的store作为'user'属性,便于获取和处理用户相关的数据以及执行用户相关的操作
user: useUserStore(),
// 把权限相关的store作为'permission'属性,用于权限相关的状态管理以及权限控制相关操作
permission: usePermissionStore(),
});
export default useStore;
// 将整合后的useStore函数导出使得在其他模块中可以导入并使用这个函数来获取整个应用的各种状态管理相关内容
export default useStore;

@ -1,18 +1,35 @@
// 从 'element-plus' 库中导入 'ElMessageBox' 和 'ElNotification' 组件,
// 'ElMessageBox' 通常用于弹出各种类型的提示框(如确认框、警告框等),
// 'ElNotification' 用于在页面上显示通知消息(如操作成功、失败等提示信息)。
import { ElMessageBox, ElNotification } from "element-plus";
// 定义名为 'notifySuccess' 的函数,用于向用户展示操作成功的通知消息,接收一个字符串类型的参数'message',该参数表示要显示的具体消息内容。
export function notifySuccess(message: string) {
ElNotification({
title: "成功",
message,
type: "success",
});
// 使用 'ElNotification' 组件来创建并显示一个通知消息框,配置如下:
// - 'title' 属性设置为 "成功",用于明确告知用户这是一个成功提示的消息框。
// -'message' 属性直接使用传入的参数'message',展示具体的提示内容。
// - 'type' 属性设置为 "success",表示这是一个成功类型的消息框,通常会有对应的成功样式(如绿色图标等)来直观体现操作成功的结果。
ElNotification({
title: "成功",
message,
type: "success",
});
}
// 定义名为'messageConfirm' 的函数,用于弹出一个确认框与用户进行交互确认,接收一个字符串类型的参数 'content',该参数表示确认框中要显示的提示内容。
export function messageConfirm(content: string) {
return ElMessageBox.confirm(content, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
center: true,
type: "warning",
});
}
// 使用 'ElMessageBox.confirm' 方法来创建并弹出一个确认框,配置如下:
// - 第一个参数 'content' 传入要显示的提示内容,即告知用户需要确认的具体事项。
// - 第二个参数 "系统提示" 作为确认框的标题,用于明确提示的来源或者主题。
// - 第三个参数是一个配置对象,具体配置如下:
// - 'confirmButtonText' 属性设置为 "确定",定义确认按钮上显示的文本内容。
// - 'cancelButtonText' 属性设置为 "取消",定义取消按钮上显示的文本内容。
// - 'center' 属性设置为 true使确认框在页面中居中显示提升视觉效果和用户交互体验。
// - 'type' 属性设置为 "warning",表示这是一个警告类型的确认框,通常会有对应的警告样式(如黄色图标等)来提醒用户谨慎操作。
return ElMessageBox.confirm(content, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
center: true,
type: "warning",
});
}

@ -1,10 +1,15 @@
<template>
<!-- 整体的404页面容器通过绝对定位和translate属性让其在页面居中显示 -->
<div class="wscn-http404-container">
<div class="wscn-http404">
<div class="pic-404">
<!-- 主404图片 -->
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
<!-- 左侧云朵小图片通过绝对定位和动画设置实现动态效果 -->
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
<!-- 中间云朵小图片 -->
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
<!-- 右侧云朵小图片 -->
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
</div>
<div class="bullshit">
@ -17,6 +22,7 @@
<div class="bullshit__info">
对不起您正在寻找的页面不存在尝试检查URL的错误然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容
</div>
<!-- 路由链接点击可返回首页 -->
<router-link to="/index" class="bullshit__return-home">
返回首页
</router-link>
@ -26,229 +32,347 @@
</template>
<script setup lang="ts">
import { computed } from "vue";
let message = computed(() => {
return '找不到网页!'
})
import { computed } from "vue";
// 'message'
let message = computed(() => {
return '找不到网页!'
})
//
const initAnimation = () => {
const elements = document.querySelectorAll('[animation-name]');
elements.forEach(element => {
const animationName = element.getAttribute('animation-name');
const animationDuration = element.getAttribute('animation-duration');
const animationTimingFunction = element.getAttribute('animation-timing-function');
const animationDelay = element.getAttribute('animation-delay');
const animationFillMode = element.getAttribute('animation-fill-mode');
//
const animation = element.animate([
{ opacity: 0 },
{ opacity: 1 }
], {
duration: parseInt(animationDuration) * 1000,
easing: animationTimingFunction,
delay: parseInt(animationDelay) * 1000,
fill: animationFillMode === 'forwards'? 'forwards' : 'none'
});
animation.play();
});
}
//
window.onload = initAnimation;
</script>
<style lang="scss" scoped>
.wscn-http404-container {
transform: translate(-50%, -50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 {
position: relative;
width: 1200px;
padding: 0 50px;
overflow: hidden;
.pic-404 {
// 404使
.wscn-http404-container {
transform: translate(-50%, -50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 {
position: relative;
float: left;
width: 600px;
width: 1200px;
padding: 0 50px;
overflow: hidden;
&__parent {
width: 100%;
}
&__child {
position: absolute;
.pic-404 {
position: relative;
float: left;
width: 600px;
overflow: hidden;
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
&__parent {
width: 100%;
}
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&__child {
position: absolute;
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
// Chrome-webkit-Firefox-moz-
@-webkit-keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
20% {
top: 120px;
left: 460px;
opacity: 1;
@-webkit-keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
80% {
top: 180px;
left: 340px;
opacity: 1;
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
100% {
top: 200px;
left: 300px;
opacity: 0;
@-webkit-keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
&__return-home {
display: block;
.bullshit {
position: relative;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
width: 300px;
padding: 30px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
100% {
transform: translateY(0);
opacity: 1;
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
//
@-webkit-keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
}
</style>
</style>

@ -1,16 +1,25 @@
<template>
<!-- 整个页面的最外层容器用于包裹所有的页面内容设置了类名用于样式绑定 -->
<div class="dashboard-container">
<!-- el-row 组件用于创建行布局通过 :gutter 属性设置列之间的间隔为 40px同时添加了类名 panel-group用于样式区分 -->
<el-row :gutter="40" class="panel-group">
<!-- el-col 组件用于创建列布局根据不同屏幕尺寸xssmlg设置列所占的份数这里在各种屏幕尺寸下都占一定比例用于展示卡片式面板添加了类名 card-panel-col方便样式设置 -->
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel">
<!-- 用于包裹卡片面板中图标部分的容器添加了类名和图标相关的自定义类方便样式控制和图标显示相关操作 -->
<div class="card-panel-icon-wrapper icon-view">
<!-- svg-icon 组件用于显示特定的 SVG 图标通过 icon-class 属性指定图标类名size 属性设置图标大小class-tagName 属性添加自定义类名方便样式调整 -->
<svg-icon icon-class="dashboard" size="4em" class-tagName="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">
<!-- 显示卡片面板中的文本描述信息这里是车流统计总量 -->
车流统计总量
</div>
<span class="card-panel-num">5.20w</span>
<span class="card-panel-num">
<!-- 显示具体的数值信息这里示例为5.20w实际可能根据数据动态变化 -->
5.20w
</span>
</div>
</div>
</el-col>
@ -58,10 +67,15 @@
</el-row>
<!-- 另一个 el-row 组件用于布局下方的图表部分设置列间隔为 32px -->
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<div class="title">上周车流量统计🚀</div>
<div class="title">
<!-- 图表的标题这里是上周车流量统计🚀用于说明图表展示的内容 -->
上周车流量统计🚀
</div>
<!-- Echarts 组件用于展示具体的图表通过 :options 属性绑定对应的图表配置数据这里是 carFlowheight 属性设置图表的高度为 350px -->
<Echarts :options="carFlow" height="350px"></Echarts>
</div>
</el-col>
@ -86,342 +100,281 @@
</template>
<script setup lang="ts">
import { TagVO } from "@/api/article/types";
import TagCloud from "@/components/TagCloud/index.vue";
import { onMounted, reactive, ref } from "vue";
const tagList = ref<TagVO[]>([]);
const viewCount = ref(500);
const messageCount = ref(0);
const userCount = ref(0);
const tagLoad = ref(false);
const articleCount = ref(0);
// const articleStatisticsList = ref<ArticleStatisticsVO[]>([]);
let algorithmView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
// TagVO
import { TagVO } from "@/api/article/types";
// TagCloud 使
import TagCloud from "@/components/TagCloud/index.vue";
// Vue onMountedreactiveref
import { onMounted, reactive, ref } from "vue";
// tagList TagVO
const tagList = ref<TagVO[]>([]);
// viewCount 500
const viewCount = ref(500);
// messageCount 0
const messageCount = ref(0);
// userCount 0
const userCount = ref(0);
// tagLoad false
const tagLoad = ref(false);
// articleCount 0
const articleCount = ref(0);
// ArticleStatisticsVO
// const articleStatisticsList = ref<ArticleStatisticsVO[]>([]);
// algorithmView Echarts
let algorithmView = reactive({
xAxis: {
// x
data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: ['算法1', '算法2']
},
series: [
{
name: '算法1',
itemStyle: {
color: '#FF005A'
},
lineStyle: {
color: '#FF005A',
width: 2
},
smooth: true,
type: 'line',
data: [
10, 12, 13, 15, 17, 20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
grid: {
//
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
{
name: '算法2',
smooth: true,
type: 'line',
itemStyle: {
color: '#3888fa'
tooltip: {
//
trigger: 'axis',
axisPointer: {
type: 'cross'
},
lineStyle: {
color: '#3888fa',
width: 2
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
//
data: ['算法1', '算法2']
},
series: [
{
name: '算法1',
itemStyle: {
// 1
color: '#FF005A'
},
lineStyle: {
// 线
color: '#FF005A',
width: 2
},
smooth: true,
type: 'line',
data: [
10, 12, 13, 15, 17, 20, 22, 25, 28, 30, 32, 35 // 1
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
areaStyle: {
color: '#f3f8ff'
{
name: '算法2',
smooth: true,
type: 'line',
itemStyle: {
color: '#3888fa'
},
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
},
data: [
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 // 2
] as number[],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
});
// interfaceView Echarts
let interfaceView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
data: [
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 //
] as number[],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
});
let interfaceView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
series: [
{
name: '接口调用',
itemStyle: {
color: 'rgb(64,201,198)'
},
lineStyle: {
color: 'rgb(64,201,198)',
width: 2
series: [
{
name: '接口调用',
itemStyle: {
color: 'rgb(64,201,198)'
},
lineStyle: {
color: 'rgb(64,201,198)',
width: 2
},
smooth: true,
type: 'line',
data: [
20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
smooth: true,
type: 'line',
data: [
20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
]
});
// category Echarts
let category = reactive({
tooltip: {
//
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
]
});
let category = reactive({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
top: "bottom",
},
series: [
{
name: '分类统计',
type: 'pie',
radius: [15, 95],
center: ['50%', '38%'],
roseType: 'area',
itemStyle: {
borderRadius: 6
},
data: [{ value: 111, name: '小型车' },
{ value: 123, name: '中型车' },
{ value: 132, name: '大型车' },
] as {
value: number;
name: string;
}[],
}
]
});
let carFlow = reactive({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
color: ['#58AFFF'],
grid: {
left: '0%',
right: '0%',
bottom: '0%',
top: '10%',
containLabel: true
},
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7",] as string[],
axisTick: {
alignWithLabel: true
}
},
yAxis: {
type: 'value',
axisTick: {
show: false
}
},
series: [
{
name: '数据',
type: 'bar',
data: [111, 123, 132, 118, 105, 130, 143,] as number[]
}
]
});
const getList = () => {
};
onMounted(() => {
getList();
})
</script>
<style lang="scss" scoped>
.title {
font-size: 14px;
color: var(--el-text-color-secondary);
font-weight: 700;
}
.data-card {
background: var(--el-bg-color-overlay);
padding: 1rem;
}
.dashboard-container {
padding: 32px;
background: var(--el-bg-color-page);
position: relative;
.github-corner {
position: absolute;
top: 0px;
border: 0;
right: 0;
}
.chart-wrapper {
background: var(--el-bg-color-overlay);
padding: 1rem;
margin-bottom: 2rem;
}
}
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: var(--el-bg-color-overlay);
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
border-color: rgba(0, 0, 0, .05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
legend: {
//
top: "bottom",
},
series: [
{
name: '分类统计',
type: 'pie',
radius: [15, 95],
center: ['50%', '38%'],
roseType: 'area',
itemStyle: {
borderRadius: 6
},
data: [{ value: 111, name: '小型车' },
{ value: 123, name: '中型车' },
{ value: 132, name: '大型车' },
] as {
value: number;
name: string;
}[],
}
.icon-people {
background: #40c9c6;
]
});
// carFlow Echarts
let carFlow = reactive({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
.icon-message {
background: #36a3f7;
},
color: ['#58AFFF'],
grid: {
left: '0%',
right: '0%',
bottom: '0%',
top: '10%',
containLabel: true
},
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7",] as string[],
axisTick: {
alignWithLabel: true
}
.icon-money {
background: #f4516c;
},
yAxis: {
type: 'value',
axisTick: {
show: false
}
.icon-view {
background: #34bfa3
},
series: [
{
name: '数据',
type: 'bar',
data: [111, 123, 132, 118, 105, 130, 143,] as number[]
}
}
]
});
.icon-people {
color: #40c9c6;
}
// getList
const getList = () => {
.icon-message {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
}
};
.icon-view {
color: #34bfa3
}
// 使 onMounted getList getList
onMounted(() => {
getList();
})
</script>
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
<style lang="scss" scoped>
.title {
// 使
font-size: 14px;
color: var(--el-text-color-secondary);
font-weight: 700;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.data-card {
// 使
background: var(--el-bg-color-overlay);
padding: 1rem;
}
.card-panel-text {
line-height: 18px;
color: var(--el-text-color-secondary);
font-size: 16px;
margin-bottom: 12px;
}
.dashboard-container {
// 使
padding: 32px;
background: var(--el-bg-color-page);
position: relative;
.card-panel-num {
font-size: 20px;
}
.github-corner {
// top: 0pxright: 0 GitHub
position: absolute;
top: 0px;
border: 0;
right: 0;
}
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
@media (max-width:550px) {
.card-panel-description {
display: none;
// 使
background: var(--el-bg-color-overlay);
padding: 1rem;
margin-bottom: 2rem;
}
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.panel-group {
margin-top: 18px;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
.card-panel-col {
margin-bottom: 32px;
}
}
}
</style>
.card-panel {
// 使
height: 108px;
cursor: pointer;
font-size: 12px;

@ -1,127 +1,173 @@
<template>
<!-- 登录页面的外层容器通过绑定内联样式设置背景图片其图片路径来源于变量 `Img_1`同时添加了 `login` 类名用于后续样式设置 -->
<div class="login" :style="{ 'background-image': 'url(' + Img_1 + ')' }">
<!-- 使用 `el-form` 组件创建登录表单通过 `ref` 绑定表单实例引用 `ruleFormRef``model` 属性绑定表单数据对象 `loginForm``rules` 属性绑定表单验证规则 `rules`并添加 `login-form` 类名用于样式定制 -->
<el-form ref="ruleFormRef" :model="loginForm" :rules="rules" class="login-form">
<!-- 页面标题显示为 "MTSP系统"用于标识该登录页面所属系统 -->
<h3 class="title">MTSP系统</h3>
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框这里是用户名输入框相关部分`prop` 属性对应表单验证规则中的字段名用于验证该输入框输入内容是否符合规则 -->
<el-form-item prop="username">
<!-- `el-input` 组件用于创建文本输入框通过 `v-model` 双向绑定数据到 `loginForm` 中的 `username` 属性设置输入框类型为 `text`大小为 `large`并添加占位提示文字 "账号" -->
<el-input v-model="loginForm.username" type="text" size="large" placeholder="账号">
<!-- 使用具名插槽 `#prefix`在输入框前面添加一个 `svg-icon` 图标组件显示用户图标增强输入框的可视化提示 -->
<template #prefix><svg-icon icon-class="user"></svg-icon></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" show-password size="large" placeholder="密码"
@keyup.enter="handleLogin(ruleFormRef)">
<!-- 同样使用具名插槽 `#prefix`在密码输入框前添加一个 `svg-icon` 图标组件显示密码图标提示该输入框用于输入密码 -->
<template #prefix><svg-icon icon-class="password"></svg-icon></template>
<!-- 监听键盘按下回车键事件触发 `handleLogin` 方法进行登录操作方便用户快速提交登录表单 -->
@keyup.enter="handleLogin(ruleFormRef)"
</el-input>
</el-form-item>
<el-form-item>
<!-- `el-button` 组件用于创建登录按钮通过 `:loading` 属性绑定 `loading` 变量来控制按钮是否显示加载状态按钮类型为 `primary`通常表示主要操作按钮样式上会有突出显示点击按钮时通过 `@click.prevent` 阻止默认行为并触发 `handleLogin` 方法进行登录操作设置按钮宽度为 `100%`占满父容器宽度 -->
<el-button :loading="loading" type="primary" @click.prevent="handleLogin(ruleFormRef)" style="width:100%;">
<!-- 根据 `loading` 变量的值来切换按钮显示的文字内容未加载时显示 "登 录"加载中时显示 "登 录中..." -->
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
</el-form-item>
</el-form>
<!-- 底部 -->
<!-- 页面底部部分用于显示版权信息等相关内容 -->
<div class="el-login-footer">
<span>Copyright © 2023 By Pan</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from "element-plus";
import Img_1 from "@/assets/images/index.jpg";
import router from "@/router";
import useStore from '@/store';
import { FormInstance, FormRules } from 'element-plus';
import { reactive, ref } from 'vue';
const { user } = useStore();
const ruleFormRef = ref<FormInstance>();
const loading = ref(false);
const loginForm = reactive({
username: "pan",
password: "123456",
});
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
password: [{ required: true, message: "请输入密码", trigger: "blur" }, { min: 6, message: "密码不能少于6位", trigger: "blur" }],
});
const handleLogin = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
loading.value = true;
user.LogIn(loginForm).then((data: any) => {
//
console.log(data)
if (data.code === 200) {
ElMessage({
message: "登录成功",
type: "success",
duration: 0.75 * 1000,
onClose: () => {
window.location.reload();
},
});
router.replace({ path: "/" });
}
loading.value = false;
}).catch(() => {
// `element-plus` `ElMessage`
import { ElMessage } from "element-plus";
// `@/assets/images/index.jpg`
import Img_1 from "@/assets/images/index.jpg";
//
import router from "@/router";
// `useStore` Vuex
import useStore from '@/store';
// `element-plus` `FormInstance` `FormRules`使
import { FormInstance, FormRules } from 'element-plus';
// `vue` `reactive` `ref`
import { reactive, ref } from 'vue';
// `useStore` `user` `user.LogIn`
const { user } = useStore();
// `ruleFormRef` `el-form` 便 `undefined`
const ruleFormRef = ref<FormInstance>();
// `loading` `false` `true` `false`
const loading = ref(false);
// `loginForm`使 `el-form` `model`
const loginForm = reactive({
username: "pan",
password: "123456",
});
// `rules` `FormRules`
// `username` `trigger: "blur"` ""
// `password` ""6 "6"
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
password: [{ required: true, message: "请输入密码", trigger: "blur" }, { min: 6, message: "密码不能少于6位", trigger: "blur" }],
});
// `handleLogin` `FormInstance` `undefined` `formEl`
const handleLogin = async (formEl: FormInstance | undefined) => {
// `formEl` `undefined`
if (!formEl) return;
// `validate` `valid` `true` `false`
await formEl.validate((valid) => {
if (valid) {
// `loading` `true`使
loading.value = true;
// `user` `LogIn` `loginForm` `Promise` `then` `catch`
user.LogIn(loginForm).then((data: any) => {
// 便
console.log(data)
// `code` `200`
if (data.code === 200) {
// 使 `ElMessage` "" `success`绿 `0.75 * 1000` 0.75
ElMessage({
message: "登录成功",
type: "success",
duration: 0.75 * 1000,
onClose: () => {
//
window.location.reload();
},
});
// `"/"`
router.replace({ path: "/" });
}
// `loading` `false`使
loading.value = false;
}).catch(() => {
// `loading` `false`使
loading.value = false;
});
} else {
// `loading` `false`使 `false`
loading.value = false;
});
} else {
loading.value = false;
return false;
}
})
}
return false;
}
})
}
</script>
<style>
.login {
display: flex;
justify-content: center;
align-items: center;
/* 登录页面整体容器的样式设置 */
.login {
/* 使用 flex 布局,使内部元素在水平和垂直方向上居中对齐,常用于页面整体布局,让内容在页面中看起来更规整 */
display: flex;
justify-content: center;
align-items: center;
background-image: url("https://static.ttkwsd.top/config/0d7d8d691e644989b72ddda5f695aca2.jpg");
background-size: cover;
height: 660px;
height: 100%;
}
/* 设置背景图片,虽然在模板中也通过内联样式设置了背景图片,这里可能是默认的背景图设置,具体的优先级和使用场景需根据项目实际情况确定,图片会自适应铺满整个容器 */
background-image: url("https://static.ttkwsd.top/config/0d7d8d691e644989b72ddda5f695aca2.jpg");
background-size: cover;
/* 设置容器高度,这里先设置了固定高度 `660px`,又设置了 `height: 100%`,可能在不同场景下会有不同的高度表现,具体取决于父容器的高度设置等因素 */
height: 660px;
height: 100%;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
}
/* 标题("MTSP系统")的样式设置,使其在水平方向上居中显示,上下外边距分别设置为 `0` 和 `30px`,文字颜色为灰色调(`#707070`),用于页面的视觉效果调整 */
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
}
/* 登录表单的样式设置,设置了边框圆角、白色背景色、固定宽度以及内边距等,使其在页面中有一个清晰的外观样式,方便用户输入信息 */
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
/* 可能用于显示登录提示信息的样式类(代码中未看到使用该类的地方),设置了字体大小、文本居中对齐以及颜色等属性,用于统一提示信息的显示样式 */
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
/* 页面底部版权信息等相关内容的样式设置,固定高度、垂直居中对齐、固定在页面底部(`position: fixed; bottom: 0;`),占满页面宽度,文本居中对齐,设置了白色字体颜色、字体家族、字体大小以及字间距等属性,用于展示版权等相关说明信息 */
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
</style>
<style>
div#app {
height: 100%;
}
/* 设置 `div#app` 元素的高度为 `100%`,可能用于确保整个应用在页面中占满可视区域等布局相关的目的,具体效果取决于整个页面的结构和其他相关样式设置 */
div#app {
height: 100%;
}
</style>

@ -1,13 +1,18 @@
<template>
<!-- 整个页面的最外层容器用于包裹所有页面内容添加了类名 `dashboard-container`方便后续通过样式类来设置整体的页面样式 -->
<div class="dashboard-container">
<!-- `el-row` 组件用于创建行布局通过 `:gutter` 属性设置列与列之间的间隔为 32px用于对页面中的不同部分进行布局划分 -->
<el-row :gutter="32">
<!-- `el-col` 组件用于创建列布局根据不同屏幕尺寸`xs``sm``lg`设置列所占的份数这里在 `xs` `sm` 屏幕尺寸下占满整行24 `lg` 屏幕尺寸下占 16 用于放置视频相关内容 -->
<el-col :xs="24" :sm="24" :lg="16">
<div class="chart-wrapper">
<div class="title">视频检测 🚀</div>
<!-- 此处原本可能用于展示图表注释掉了相关代码现在主要用于视频播放部分 -->
<!-- <Echarts :options="category" height="350px"></Echarts> -->
<!-- 视频播放 -->
<!-- 视频播放区域的容器设置了高度上边距等样式用于展示视频内容 -->
<div style="height:470px; margin-top:20px">
<!-- `video` 标签用于嵌入视频元素通过样式设置使其宽度和高度占满父容器添加了内边距和背景色设置了静音和自动播放属性同时通过 `ref` 绑定了 `videoElement`方便在脚本中操作该视频元素 -->
<video style="width:100%;height:100%; padding:10px; background-color: rgb(250, 253, 253);" muted autoplay
id="video" ref="videoElement"></video>
</div>
@ -16,10 +21,12 @@
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<div class="title">配置表单 📋</div>
<!-- 表单 -->
<!-- 表单区域的容器设置了高度上边距等样式用于放置配置表单相关内容 -->
<div style="height:470px; margin-top:20px">
<!-- `el-form` 组件用于创建表单通过 `:model` 属性绑定表单数据对象 `form``label-width` 属性设置表单标签的宽度为 80px用于整体表单的布局和样式呈现 -->
<el-form :model="form" label-width="80px">
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框或选择框等这里是视频路径通过 `v-model` 双向绑定数据到 `route.query.video`并设置该项为禁用状态可能用于展示已有的视频路径信息且不允许用户修改 -->
<el-form-item label="视频路径">
<el-input v-model="route.query.video" :disabled="true" />
</el-form-item>
@ -30,6 +37,7 @@
<el-form-item label="配置人员">
<el-select v-model="route.query.person" placeholder="请选择配置人员" :disabled="true">
<!-- `el-option` 组件用于在下拉选择框中添加可选项这里提供了PanRock两个选项 -->
<el-option label="Pan" value="Pan" />
<el-option label="Rock" value="Rock" />
</el-select>
@ -65,282 +73,241 @@
</el-row>
<el-row class="data-card">
<div class="title">算法表现 </div>
<!-- `Echarts` 组件用于展示具体的图表通过 `:options` 属性绑定对应的图表配置数据这里是 `algorithmView``height` 属性设置图表的高度为 350px用于展示算法相关的数据可视化内容 -->
<Echarts :options="algorithmView" height="350px"></Echarts>
</el-row>
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';
const route = useRoute();
import { ElMessage } from "element-plus";
import { onMounted, reactive, ref } from "vue";
import { submitMonitorForm } from '@/api/monitor';
import { wsPlayer } from '../streamingSetting/wsplayer/wsPlayer.js'; // wsPlayer.js
const videoElement = ref(null);
let player = ref(null);
onMounted(() => {
const player = videoElement.value;
if (videoElement.value) {
const player = new wsPlayer('video', form.videoUrl);
player.open();
console.log(11);
}
});
// `vue-router` `useRoute`
import { useRoute } from 'vue-router';
// `route` 便使
const route = useRoute();
// `element-plus` `ElMessage`
import { ElMessage } from "element-plus";
// `vue` `onMounted` `reactive` `ref`
import { onMounted, reactive, ref } from "vue";
// `submitMonitorForm`
import { submitMonitorForm } from '@/api/monitor';
// `wsPlayer.js` `wsPlayer.js`
import { wsPlayer } from '../streamingSetting/wsplayer/wsPlayer.js';
// `videoElement` `null` `ref` `video`
const videoElement = ref(null);
// `player` `null`
let player = ref(null);
// 使 `onMounted`
onMounted(() => {
// `videoElement` `player`
const player = videoElement.value;
// `videoElement` `video`
if (videoElement.value) {
// `wsPlayer` `wsPlayer.js` `video` `id` `'video'``form.videoUrl`
const player = new wsPlayer('video', form.videoUrl);
// `open` `wsPlayer`
player.open();
console.log(11);
}
});
//
const form = reactive({
videoUrl: 'ws://127.0.0.1/live/test.live.mp4',
person: '',
isAlarm: false,
remark: '',
mode: '',
threshold: '',
location: '',
})
// `form`
const form = reactive({
videoUrl: 'ws://127.0.0.1/live/test.live.mp4',
person: '',
isAlarm: false,
remark: '',
mode: '',
threshold: '',
location: '',
})
//
const formSubmit = () => {
console.log(111)
// submitMonitorForm
submitMonitorForm(form)
.then(response => {
const result: Result<any> = response.data;
//
console.log(result);
ElMessage({
message: "提交成功",
type: "success",
duration: 2 * 1000,
onClose: () => {
window.location.reload();
// `formSubmit`
const formSubmit = () => {
console.log(111)
// `submitMonitorForm` `Promise` `then` `catch`
submitMonitorForm(form)
.then(response => {
// `Result` `data` `result`
const result: Result<any> = response.data;
// 便
console.log(result);
// 使 `ElMessage` `success`绿 2 `2 * 1000`
ElMessage({
message: "提交成功",
type: "success",
duration: 2 * 1000,
onClose: () => {
//
window.location.reload();
},
});
})
.catch(error => {
// 便
console.error(error);
// 使 `ElMessage` `danger` 2
ElMessage({
message: "提交失败,请稍后再试!",
type: "danger",
duration: 2 * 1000,
onClose: () => {
window.location.reload();
},
});
});
};
// `algorithmView` `Echarts` 线
let algorithmView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
});
})
.catch(error => {
console.error(error);
ElMessage({
message: "提交失败,请稍后再试!",
type: "danger",
duration: 2 * 1000,
onClose: () => {
window.location.reload();
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
});
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: ['准确', '快速']
},
series: [
{
name: '准确',
itemStyle: {
color: '#FF005A'
},
lineStyle: {
color: '#FF005A',
width: 2
},
smooth: true,
type: 'line',
data: [
10, 12, 13, 15, 17, 20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '快速',
smooth: true,
type: 'line',
itemStyle: {
color: '#3888fa'
},
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
},
data: [
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 //
] as number[],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
});
};
let algorithmView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: ['准确', '快速']
},
series: [
{
name: '准确',
itemStyle: {
color: '#FF005A'
},
lineStyle: {
color: '#FF005A',
width: 2
},
smooth: true,
type: 'line',
data: [
10, 12, 13, 15, 17, 20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '快速',
smooth: true,
type: 'line',
itemStyle: {
color: '#3888fa'
},
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
},
data: [
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 //
] as number[],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
});
</script>
<style lang="scss" scoped>
.title {
font-size: 18px;
color: rgba(0, 0, 0, 0.836);
font-weight: 700;
}
.data-card {
background: var(--el-bg-color-overlay);
padding: 1rem;
}
.dashboard-container {
padding: 32px;
background: var(--el-bg-color-page);
position: relative;
.github-corner {
position: absolute;
top: 0px;
border: 0;
right: 0;
}
.chart-wrapper {
background: var(--el-bg-color-overlay);
padding: 1rem;
margin-bottom: 2rem;
}
}
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: var(--el-bg-color-overlay);
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
border-color: rgba(0, 0, 0, .05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-people {
background: #40c9c6;
}
.icon-message {
background: #36a3f7;
}
.icon-money {
background: #f4516c;
}
.icon-view {
background: #34bfa3
}
/* 标题样式设置,统一页面中各部分标题的字体大小、颜色(设置了透明度,呈现较深的灰色)以及字体粗细,使标题在页面中有清晰、一致的视觉效果 */
.title {
font-size: 18px;
color: rgba(0, 0, 0, 0.836);
font-weight: 700;
}
.icon-people {
color: #40c9c6;
/* `data-card` 类的样式设置,用于特定区域(可能是展示算法表现图表的区域)的背景颜色设置(使用了变量,可能是一种覆盖层的背景色)和内边距添加,使其在页面中有合适的展示效果和间距 */
.data-card {
background: var(--el-bg-color-overlay);
padding: 1rem;
}
.icon-message {
color: #36a3f7;
/* `dashboard-container` 类的样式设置,用于整体页面容器的样式布局,添加内边距、设置背景颜色(同样使用了变量,可能是页面主体的背景色),并设置相对定位,方便内部元素进行相对定位等布局操作 */
.dashboard-container {
padding: 32px;
background: var(--el-bg-color-page);
position: relative;
.github-corner {
// `github-corner` `top: 0px``right: 0` GitHub
position: absolute;
top: 0px;
border: 0;
right: 0;
}
.chart-wrapper {
// `chart-wrapper` 使
background: var(--el-bg-color-overlay);
padding: 1rem;
margin-bottom: 2rem;
}
}
.icon-money {
color: #f4516c;
}
.icon-view {
color: #34bfa3
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: var(--el-text-color-secondary);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
@media (max-width:550px) {
.card-panel-description {
display: none;
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
}
}
}
</style>
/* `panel-group` 类及相关内部类的样式设置,不过从页面结构来看,在当前模板中未直接使用到这个类,可能是用于其他相似布局场景或者后续扩展的样式代码,以下是其详细的样式注释 */
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: var(--el-bg-color-overlay);
box-shadow: 4px 4px 40px rgba(0, 0, 0,.05);
border-color: rgba(0, 0, 0,.05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-people {
background: #40c9c6;
}
.icon-message {
background: #36a3f7;
}
.icon-money {
background: #f4516c;
}
.icon-view {
background: #34bfa3
}
}
.icon-people {
color:

@ -1,49 +1,57 @@
<template>
<!-- 整个应用页面的最外层容器添加类名 `app-container`用于后续统一设置页面的整体样式 -->
<div class="app-container">
<!-- 搜索栏 -->
<!-- 搜索栏部分使用 `el-form` 组件创建一个内联表单用于输入搜索关键词并触发搜索操作 -->
<el-form :model="queryParams" :inline="true">
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框这里是监控id输入框相关部分`label` 属性用于显示该项的标签文字 -->
<el-form-item label="监控id">
<!-- `el-input` 组件用于创建文本输入框通过 `v-model` 双向绑定数据到 `queryParams.keyword`设置输入框宽度占位提示文字以及可清空内容的功能同时监听键盘按下回车键事件触发 `handleQuery` 方法进行搜索操作 -->
<el-input @keyup.enter="handleQuery" v-model="queryParams.keyword" style="width: 200px" placeholder="请输入监控id"
clearable />
</el-form-item>
<el-form-item>
<!-- `el-button` 组件用于创建搜索按钮按钮类型为 `primary`通常表示主要操作按钮样式上会有突出显示添加搜索图标点击按钮时触发 `handleQuery` 方法进行搜索 -->
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<!-- 操作按钮部分使用 `el-row` 组件创建行布局通过 `:gutter` 属性设置列之间的间隔为 10px并添加类名 `mb15`可能用于设置底部外边距不过样式部分没看到具体定义推测是自定义的样式类名 -->
<el-row :gutter="10" class="mb15">
<!-- `el-col` 组件用于创建列布局`:span` 属性设置列所占的份数这里占 1.5 用于放置新增按钮 -->
<el-col :span="1.5">
<!-- `el-button` 组件用于创建按钮按钮类型为 `primary` 且为 `plain`表示简洁样式通常是只有边框和文字颜色变化的按钮添加加号图标点击按钮时触发 `openModel` 方法传入 `undefined` 参数用于打开新增对话框等相关操作 -->
<el-button type="primary" plain icon="Plus" @click="openModel(undefined)"></el-button>
</el-col>
<el-col :span="1.5">
<!-- `el-button` 组件用于创建按钮按钮类型为 `danger`通常表示危险操作按钮样式上会有相应提示比如红色系颜色且为 `plain`添加删除图标通过 `:disabled` 属性设置按钮为禁用状态这里值为 `1`推测是布尔值的一种写法实际应该为 `true`点击按钮时触发 `handleDelete` 方法目前代码中未看到该方法的具体实现传入 `undefined` 参数可能用于批量删除相关操作 -->
<el-button type="danger" plain :disabled="1" icon="Delete" @click="handleDelete(undefined)"></el-button>
</el-col>
<!-- 引入自定义的 `right-toolbar` 组件通过 `v-model:showSearch` 进行双向数据绑定可能用于控制搜索栏的显示隐藏等相关状态同时监听 `@queryTable` 事件触发 `getList` 方法用于刷新列表数据等操作 -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 表格展示 -->
<!-- 表格展示部分使用 `el-table` 组件展示监控相关的数据列表通过 `border` 属性设置显示表格边框`:data` 属性绑定数据来源为 `MonitorList`通过 `v-loading` 属性绑定 `loading` 变量来控制表格是否显示加载状态 -->
<el-table border :data="MonitorList" v-loading="loading">
<!-- `el-table-column` 组件用于定义表格的列这里设置列类型为 `selection`用于在表格每行前面显示一个复选框方便进行多选操作设置列宽度为 55px -->
<el-table-column type="selection" width="55" />
<!-- id -->
<!-- 监控ID列的定义通过 `prop` 属性指定对应的数据字段为 `id``label` 属性设置列标题为监控ID`align` 属性设置内容居中对齐`width` 属性设置列宽度为 100px -->
<el-table-column prop="id" label="监控ID" align="center" width="100"></el-table-column>
<!-- 视频路径 -->
<!-- 视频路径列的定义同理指定数据字段为 `video`设置标题对齐方式和宽度等属性 -->
<el-table-column prop="video" label="视频路径" align="center" width="250"></el-table-column>
<!-- 拉流路径 -->
<!-- 拉流路径列的定义 -->
<el-table-column prop="url" label="拉流路径" align="center" width="250"></el-table-column>
<!-- 监控阈值 -->
<!-- 监控阈值列的定义 -->
<el-table-column prop="threshold" label="监控阈值" align="center" width="100"></el-table-column>
<!-- 配置人员 -->
<!-- 配置人员列的定义 -->
<el-table-column prop="person" label="配置人员" align="center" width="100"></el-table-column>
<!-- 模式 -->
<!-- 算法模式列的定义 -->
<el-table-column prop="mode" label="算法模式" align="center" width="100"></el-table-column>
<!-- 警报状态 -->
<!-- 警报状态列的定义 -->
<el-table-column prop="is_alarm" label="警报状态" align="center" width="100"></el-table-column>
<!-- 监控地点 -->
<!-- 监控地点列的定义设置了较宽的列宽度为 300px -->
<el-table-column prop="location" label="监控地点" align="center" width="300"></el-table-column>
<!-- 创建时间 -->
<!-- 创建时间列的定义设置了列宽度并通过具名插槽 `#default` 自定义列内容的显示方式这里使用 `el-date-picker` 组件以日期时间选择器的形式展示创建时间数据同时设置该选择器为禁用状态 -->
<el-table-column prop="create_time" width="250" label="创建时间" align="center">
<template #default="{ row }">
<el-date-picker :disabled="1" type="datetime" v-model="row.create_time" format="YYYY-MM-DD hh:mm:ss"
@ -52,7 +60,7 @@
</template>
</el-table-column>
<!-- 操作 -->
<!-- 操作列的定义设置列标题对齐方式和宽度同样通过具名插槽 `#default` 自定义列内容这里放置了编辑查看两个按钮分别绑定对应的点击事件方法用于对每行数据进行相应操作 -->
<el-table-column label="操作" align="center" width="200">
<template #default="scope">
<el-button type="primary" icon="Edit" link @click="openModel(scope.row)">
@ -65,53 +73,49 @@
</el-table-column>
</el-table>
<!-- 分页 -->
<!-- 分页部分引入自定义的 `pagination` 组件可能是用于实现分页功能的通用组件通过 `v-if` 指令根据 `count` 的值判断是否显示分页组件 `count > 0` 时显示`:total` 属性设置总数据条数通过 `v-model:page` `v-model:limit` 分别双向绑定当前页码和每页显示条数同时监听 `@pagination` 事件触发 `getList` 方法用于获取对应页码的数据列表 -->
<pagination v-if="count > 0" :total="count" v-model:page="queryParams.current" v-model:limit="queryParams.size"
@pagination="getList" />
<!-- 添加或修改对话框 -->
<!-- 添加或修改对话框部分使用 `el-dialog` 组件创建一个对话框设置标题通过 `v-model` 双向绑定控制对话框的显示隐藏状态设置宽度以及将对话框挂载到 `body` 元素下`append-to-body` 属性用于添加或修改监控相关信息 -->
<el-dialog title="修改监控表单" v-model="update" width="500px" append-to-body>
<!-- `el-form` 组件用于创建表单通过 `ref` 绑定表单实例引用 `FormRef``label-width` 属性设置表单标签的宽度为 100px`:model` 属性绑定表单数据对象 `monitorForm``:rules` 属性绑定表单验证规则 `rules`用于整体表单的布局数据绑定和验证等操作 -->
<el-form ref="FormRef" label-width="100px" :model="monitorForm" :rules="rules">
<!-- 视频路径表单项的定义通过 `el-form-item` 组件包裹 `el-input` 输入框设置标签文字占位提示以及通过 `v-model` 双向绑定数据到 `monitorForm.video`并设置输入框宽度 -->
<el-form-item label="视频路径" prop="video">
<el-input placeholder="请输入视频路径" v-model="monitorForm.video" style="width: 250px;" />
</el-form-item>
<!-- 拉流路径表单项的定义同理绑定到 `monitorForm.url` -->
<el-form-item label="拉流路径" prop="video">
<el-input placeholder="请输入拉流路径" v-model="monitorForm.url" style="width: 250px;" />
</el-form-item>
<!-- 监控阈值表单项的定义 -->
<el-form-item label="监控阈值" prop="threshold">
<el-input placeholder="请输入监控阈值" v-model="monitorForm.threshold" style="width: 250px;" />
</el-form-item>
<!-- 配置人员表单项的定义使用 `el-select` 下拉选择框通过 `v-model` 绑定数据到 `monitorForm.person`并添加了两个可选项PanRock -->
<el-form-item label="配置人员" prop="person">
<el-select v-model="monitorForm.person" placeholder="请选择配置人员">
<el-option label="Pan" value="Pan" />
<el-option label="Rock" value="Rock" />
</el-select>
</el-form-item>
<!-- 模式选择表单项的定义使用 `el-radio-group` 单选框组通过 `v-model` 绑定数据到 `monitorForm.mode`内部放置了快速模式精确模式两个单选框选项 -->
<el-form-item label="模式选择">
<el-radio-group v-model="monitorForm.mode">
<el-radio label="快速模式" />
<el-radio label="精确模式" />
</el-radio-group>
</el-form-item>
<!-- 开启警报表单项的定义使用 `el-switch` 开关组件通过 `v-model` 绑定数据到 `monitorForm.is_alarm`用于控制警报的开启关闭状态 -->
<el-form-item label="开启警报">
<el-switch v-model="monitorForm.is_alarm" />
</el-form-item>
<!-- 监控地点表单项的定义 -->
<el-form-item label="监控地点" prop="location">
<el-input placeholder="请输入监控地点" v-model="monitorForm.location" style="width: 250px;" />
</el-form-item>
</el-form>
<!-- 对话框底部的自定义内容部分通过具名插槽 `#footer` 定义放置了确定取消两个按钮分别绑定对应的点击事件方法用于提交表单数据或取消操作关闭对话框 -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@ -121,138 +125,48 @@
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { log } from 'console';
import { MonitorForm } from "@/api/monitor/types";
import { getmonitorList, updateMonitorForm } from '@/api/monitor';
import router from "@/router";
import { formatDate } from "@/utils/date";
import { getUserList, getUserRoleList, updateUser, updateUserStatus } from '@/api/user';
import { User, UserForm, UserQuery, UserRole } from '@/api/user/types';
import { messageConfirm, notifySuccess } from '@/utils/modal';
import { FormInstance, FormRules } from 'element-plus';
import { onMounted, reactive, ref, toRefs } from 'vue';
const FormRef = ref<FormInstance>();
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入昵称", trigger: "blur" }],
roleIdList: [{ required: true, message: "角色不能为空", trigger: "click" }]
});
const data = reactive({
count: 0,
update: false,
loading: false,
queryParams: {
current: 1,
size: 10,
} as UserQuery,
typeList: [
{
value: 1,
label: "邮箱",
},
{
value: 2,
label: "QQ",
},
{
value: 3,
label: "Gitee",
},
{
value: 4,
label: "Github",
},
],
userList: [] as User[],
userForm: {} as UserForm,
userRoleList: [] as UserRole[],
roleIdList: [] as string[],
MonitorList: [] as MonitorForm[],
monitorForm: {} as MonitorForm,
});
const {
count,
update,
loading,
queryParams,
typeList,
userList,
userForm,
userRoleList,
roleIdList,
MonitorList,
monitorForm,
} = toRefs(data);
//
const go = (monitor: MonitorForm) => {
const params = {
id: monitor.id,
video: monitor.video,
person: monitor.person,
mode: monitor.mode,
location: monitor.location,
is_alarm: monitor.is_alarm,
remark: monitor.remark,
threshold: monitor.threshold,
url: monitor.url,
};
router.push({ path: "/monitor", query: params });
};
const openModel = (monitor: MonitorForm) => {
monitorForm.value.id = monitor.id;
monitorForm.value.threshold = monitor.threshold;
monitorForm.value.location = monitor.location;
monitorForm.value.mode = monitor.mode;
monitorForm.value.person = monitor.person;
monitorForm.value.video = monitor.video;
monitorForm.value.url = monitor.url;
monitorForm.value.remark = monitor.remark;
monitorForm.value.is_alarm = false;
update.value = true;
};
const submitForm = () => {
FormRef.value?.validate((valid) => {
if (valid) {
updateMonitorForm(monitorForm.value).then(({ data }) => {
console.log(data)
if (data.code == 200) {
notifySuccess(data.msg);
getList();
}
update.value = false;
})
}
})
};
const getList = () => {
loading.value = true;
getmonitorList(queryParams.value.current).then(({ data }) => {
console.log(data)
MonitorList.value = data.data;
console.log(MonitorList.value)
loading.value = false;
})
};
//
const handleQuery = () => {
queryParams.value.current = 1;
// getList();
};
onMounted(() => {
getList();
});
</script>
<style scoped></style>
// `console` `log` 使使 `console.log`
import { log } from 'console';
// `MonitorForm` `@/api/monitor/types`
import { MonitorForm } from "@/api/monitor/types";
// `@/api/monitor`
import { getmonitorList, updateMonitorForm } from '@/api/monitor';
// `@/router`
import router from "@/router";
// `@/utils/date`
import { formatDate } from "@/utils/date";
// `@/api/user`
import { getUserList, getUserRoleList, updateUser, updateUserStatus } from '@/api/user';
// `@/api/user/types`
import { User, UserForm, UserQuery, UserRole } from '@/api/user/types';
// `@/utils/modal`
import { messageConfirm, notifySuccess } from '@/utils/modal';
// `element-plus` `FormInstance` `FormRules`使
import { FormInstance, FormRules } from 'element-plus';
// `vue` `onMounted` `reactive` `ref` `toRefs`
import { onMounted, reactive, ref, toRefs } from 'vue';
// `FormRef` `el-form` 便 `undefined`
const FormRef = ref<FormInstance>();
// `rules` `FormRules`
// `username` 使`trigger: "blur"`
// `roleIdList` `trigger: "click"`
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入昵称", trigger: "blur" }],
roleIdList: [{ required: true, message: "角色不能为空", trigger: "click" }]
});
// `data`
const data = reactive({
// 0
count: 0,
// `false` `true`
update: false,
// `false` `true` `false`
loading: false,
// `UserQuery`
queryParams: {
current: 1,

@ -1,13 +1,17 @@
<template>
<!-- 整个页面的最外层容器添加类名 `dashboard-container`用于后续通过样式类统一设置页面的整体样式 -->
<div class="dashboard-container">
<!-- `el-row` 组件用于创建行布局通过 `:gutter` 属性设置列与列之间的间隔为 32px以此对页面中的不同部分进行布局划分 -->
<el-row :gutter="32">
<!-- `el-col` 组件用于创建列布局根据不同屏幕尺寸`:xs``:sm``:lg`设置列所占的份数这里在 `xs` `sm` 屏幕尺寸下占满整行24 `lg` 屏幕尺寸下占 16 用于放置视频相关内容 -->
<el-col :xs="24" :sm="24" :lg="16">
<div class="chart-wrapper">
<div class="title">视频预览 🚀</div>
<!-- 此处原本可能用于展示图表注释掉了相关代码现在主要用于视频播放部分 -->
<!-- <Echarts :options="category" height="350px"></Echarts> -->
<!-- 视频播放 -->
<!-- 视频播放区域的容器设置了高度上边距等样式用于展示视频内容 -->
<div style="height:470px; margin-top:20px">
<!-- `video` 标签用于嵌入视频元素通过样式设置使其宽度和高度占满父容器添加了内边距和背景色设置了静音和自动播放属性同时通过 `ref` 绑定了 `videoElement`方便在脚本中操作该视频元素 -->
<video style="width:100%;height:100%; padding:10px; background-color: rgb(250, 253, 253);" muted autoplay
id="video" ref="videoElement"></video>
</div>
@ -16,10 +20,11 @@
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<div class="title">配置表单 📋</div>
<!-- 表单 -->
<!-- 表单区域的容器设置了高度上边距等样式用于放置配置表单相关内容 -->
<div style="height:470px; margin-top:20px">
<!-- `el-form` 组件用于创建表单通过 `:model` 属性绑定表单数据对象 `form``label-width` 属性设置表单标签的宽度为 80px用于整体表单的布局和样式呈现 -->
<el-form :model="form" label-width="80px">
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框或选择框等这里是视频路径通过 `v-model` 双向绑定数据到 `form.video`用户输入的视频路径值会实时更新到 `form` 对象对应的属性中 -->
<el-form-item label="视频路径">
<el-input v-model="form.video" />
</el-form-item>
@ -30,17 +35,20 @@
<el-form-item label="配置人员">
<el-select v-model="form.person" placeholder="请选择配置人员">
<!-- `el-option` 组件用于在下拉选择框中添加可选项这里提供了PanRock两个选项用户可从中选择配置人员 -->
<el-option label="Pan" value="Pan" />
<el-option label="Rock" value="Rock" />
</el-select>
</el-form-item>
<!-- <el-form-item label="配置时间">
<!-- 以下这部分代码被注释掉了可能原本计划用于配置时间的选择输入若后续需要可取消注释启用
<el-form-item label="配置时间">
<el-col>
<el-date-picker v-model="form.date1" type="date" placeholder="选择时间" style="width: 100%" />
</el-col>
</el-form-item> -->
<el-form-item label="开启警报">
<!-- `el-switch` 组件用于创建开关按钮通过 `v-model` 双向绑定数据到 `form.is_alarm`用户可通过切换开关来控制警报的开启或关闭状态 -->
<el-switch v-model="form.is_alarm" />
</el-form-item>
@ -64,7 +72,9 @@
</el-form-item>
<el-form-item>
<!-- `el-button` 组件用于创建按钮这里创建一个开启预览按钮按钮类型为 `success`通常表示成功积极的操作按钮样式上会有相应体现点击按钮时触发 `playVideo` 方法用于开启视频预览功能 -->
<div style="margin-right:20px"><el-button type="success" @click="playVideo()"></el-button></div>
<!-- 创建一个提交配置按钮按钮类型为 `primary`一般作为主要操作按钮样式突出点击按钮时触发 `formSubmit` 方法用于提交表单配置信息 -->
<div><el-button type="primary" @click="formSubmit()"></el-button></div>
</el-form-item>
</el-form>
@ -74,293 +84,8 @@
</el-row>
<el-row class="data-card">
<div class="title">算法表现 </div>
<!-- 此处原本可能用于展示图表注释掉了相关代码可能用于展示与算法表现相关的数据可视化内容 -->
<!-- <Echarts :options="algorithmView" height="350px"></Echarts> -->
</el-row>
</div>
</template>
<script setup lang="ts">
import { MonitorForm } from "@/api/monitor/types";
import { ElMessage } from "element-plus";
import { onMounted, reactive, ref } from "vue";
import { submitMonitorForm } from '@/api/monitor';
import { wsPlayer } from './wsplayer/wsPlayer.js'; // wsPlayer.js
const videoElement = ref(null);
let player = ref(null);
onMounted(() => {
});
//
const pauseVideo = () => {
if (videoElement.value) {
player.value = null;
console.log(111);
}
};
//
const playVideo = () => {
if (videoElement.value) {
const player = new wsPlayer('video', form.video);
player.open();
console.log(11);
}
};
//
const form = reactive({
video: 'ws://127.0.0.1/live/test.live.mp4',
url: '',
person: '',
is_alarm: false,
remark: '',
mode: '',
threshold: '',
location: '',
})
//
const formSubmit = () => {
console.log(111)
// submitMonitorForm
submitMonitorForm(form)
.then(response => {
const result: Result<any> = response.data;
//
console.log(result);
ElMessage({
message: "提交成功",
type: "success",
duration: 2 * 1000,
onClose: () => {
window.location.reload();
},
});
})
.catch(error => {
console.error(error);
ElMessage({
message: "提交失败,请稍后再试!",
type: "danger",
duration: 2 * 1000,
onClose: () => {
window.location.reload();
},
});
});
};
let algorithmView = reactive({
xAxis: {
data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"] as string[],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 8,
right: 35,
bottom: 0,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: ['准确', '快速']
},
series: [
{
name: '准确',
itemStyle: {
color: '#FF005A'
},
lineStyle: {
color: '#FF005A',
width: 2
},
smooth: true,
type: 'line',
data: [
10, 12, 13, 15, 17, 20, 22, 25, 28, 30, 32, 35 //
] as number[],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '快速',
smooth: true,
type: 'line',
itemStyle: {
color: '#3888fa'
},
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
},
data: [
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 //
] as number[],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
});
</script>
<style lang="scss" scoped>
.title {
font-size: 18px;
color: rgba(0, 0, 0, 0.836);
font-weight: 700;
}
.data-card {
background: var(--el-bg-color-overlay);
padding: 1rem;
}
.dashboard-container {
padding: 32px;
background: var(--el-bg-color-page);
position: relative;
.github-corner {
position: absolute;
top: 0px;
border: 0;
right: 0;
}
.chart-wrapper {
background: var(--el-bg-color-overlay);
padding: 1rem;
margin-bottom: 2rem;
}
}
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: var(--el-bg-color-overlay);
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
border-color: rgba(0, 0, 0, .05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-people {
background: #40c9c6;
}
.icon-message {
background: #36a3f7;
}
.icon-money {
background: #f4516c;
}
.icon-view {
background: #34bfa3
}
}
.icon-people {
color: #40c9c6;
}
.icon-message {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
}
.icon-view {
color: #34bfa3
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: var(--el-text-color-secondary);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
@media (max-width:550px) {
.card-panel-description {
display: none;
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
}
}
}
</style>

@ -1,110 +1,165 @@
"use strict";
import {MP4Box} from "./mp4box.all.min.js"
<template>
<!-- 整个页面的最外层容器添加类名 `app-container`用于后续通过样式类来统一设置页面整体样式 -->
<div class="app-container">
<!-- 搜索栏部分使用 `el-form` 组件创建一个内联表单方便用户输入搜索关键词并执行搜索操作 -->
<el-form :model="queryParams" :inline="true">
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框这里展示的是用户昵称输入框相关部分`label` 属性用于设置该项在表单中的标签文字 -->
<el-form-item label="用户昵称">
<!-- `el-input` 组件用于创建文本输入框通过 `v-model` 双向绑定数据到 `queryParams.keyword`意味着用户在输入框中输入的内容会实时更新到 `queryParams.keyword` 反之亦然设置输入框宽度为 200px添加占位提示文字引导用户输入并且设置为可清空内容的样式同时监听键盘回车键按下事件`@keyup.enter`触发 `handleQuery` 方法来执行搜索操作 -->
<el-input @keyup.enter="handleQuery" v-model="queryParams.keyword" style="width: 200px" placeholder="请输入用户昵称"
clearable />
</el-form-item>
<el-form-item>
<!-- `el-button` 组件用于创建搜索按钮按钮类型为 `primary`通常在页面中作为主要操作按钮会有比较突出的样式效果比如颜色等方面添加了 `Search` 图标增强可视化效果点击按钮时触发 `handleQuery` 方法来执行搜索逻辑 -->
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
</el-form-item>
</el-form>
export const wsPlayer = function(videoId, wsUrl) {
this.videoId = videoId;
this.wsUrl = wsUrl;
this.ws = null;
this.frameQueue = [];
console.log("wsPlayer v1.0.1 20220423");
}
<!-- 表格展示部分使用 `el-table` 组件展示用户相关的数据列表`border` 属性设置为显示表格边框使其看起来更清晰`:data` 属性绑定了 `userList` 数据这个数据应该是一个数组里面存放着要展示的用户相关信息`v-loading` 属性绑定了 `loading` 变量用于控制表格是否显示加载中的状态比如在数据加载过程中显示加载动画等 -->
<el-table border :data="userList" v-loading="loading">
<!-- 用户ID列的定义通过 `prop` 属性指定该列对应的数据字段名为 `id`即表格这一列展示的数据是从每行数据对象中的 `id` 属性获取的`label` 属性设置该列的标题为用户ID`align` 属性设置列内容在单元格中居中对齐`width` 属性设置该列宽度为 100px -->
<el-table-column prop="id" label="用户ID" align="center" width="100"></el-table-column>
<!-- 用户头像列的定义通过 `prop` 属性指定对应的数据字段为 `avatar`设置列标题为头像以及内容居中对齐宽度为 100px同时通过具名插槽 `#default` 来自定义该列单元格内容的显示方式这里使用 `img` 标签展示头像图片通过 `:src` 绑定头像的地址从每行数据对象的 `avatar` 属性获取并设置图片的宽度和高度为 40px -->
<el-table-column prop="avatar" label="头像" align="center" width="100">
<template #default="scope">
<img :src="scope.row.avatar" width="40" height="40" />
</template>
</el-table-column>
<!-- 用户昵称列的定义和前面类似指定对应的数据字段为 `username`设置列标题内容对齐方式以及宽度等属性用于展示用户的昵称信息 -->
<el-table-column prop="username" label="用户昵称" align="center" width="200"></el-table-column>
<!-- 用户角色列的定义通过 `prop` 属性指定对应的数据字段为 `grade`设置列标题为用户角色以及内容居中对齐不过目前该列的单元格内容展示部分没有具体设置可能后续需要添加相应的逻辑来展示角色相关信息 -->
<el-table-column prop="grade" label="用户角色" align="center">
</el-table-column>
wsPlayer.prototype.open = function () {
let sourcebuffer = null;
this.ws = new WebSocket(this.wsUrl);
this.ws.binaryType = 'arraybuffer';
let firstMessage = true;
let demux_moov = function (info) {
let codecs = [];
for (let i = 0; i < info.tracks.length; i++) {
codecs.push(info.tracks[i].codec);
}
console.log(codecs);
let video = document.getElementById(this.videoId);
let mediasource = new MediaSource();
video.src = URL.createObjectURL(mediasource);
let pre_pos = 0;
mediasource.onsourceopen = function() {
sourcebuffer = mediasource.addSourceBuffer('video/mp4; codecs="' + codecs.join(', ') + '"');
sourcebuffer.onupdateend = function() {
let pos = video.currentTime;
if(video.buffered.length > 0) {
let start = video.buffered.start(video.buffered.length - 1);
let end = video.buffered.end(video.buffered.length - 1);
//console.log("pos=" + pos + ",start=" + start + ",end=" + end);
<!-- 邮箱列的定义通过 `prop` 属性指定对应的数据字段为 `email`设置列标题为邮箱以及内容居中对齐同样目前该列的单元格内容展示部分没有进一步细化可能根据实际需求补充显示邮箱内容等逻辑 -->
<el-table-column prop="email" label="邮箱" align="center">
</el-table-column>
if (pos < start) {
//console.log("set video.currentTime pos=" + pos + ",start=" + start + ",end=" + end);
video.currentTime = start;
}
<!-- 操作列的定义设置列标题为操作内容在单元格中居中对齐宽度为 100px通过具名插槽 `#default` 自定义该列单元格内容这里放置了一个编辑按钮点击按钮会触发 `openModel` 方法传入当前行的数据通过 `scope.row` 获取用于对每行数据进行相应的编辑操作 -->
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button type="primary" icon="Edit" link @click="openModel(scope.row)">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
if(pos > end) {
//console.warn("chase frame pos=" + pos + ",start=" + start + ",end=" + end);
video.currentTime = start;
}
<!-- 分页组件部分引入自定义的 `pagination` 组件应该是用于实现分页功能的一个通用组件通过 `v-if` 指令根据 `count` 的值来判断是否显示该分页组件只有当 `count > 0`即有数据总条数大于 0表示有数据可分页时才会显示`:total` 属性设置总的数据条数通过 `v-model:page` `v-model:limit` 分别进行双向数据绑定绑定的是 `queryParams` 中的 `current`当前页码 `size`每页显示条数属性意味着页面和组件之间可以相互传递和更新这些分页相关的数据同时监听 `@pagination` 事件当该事件被触发时比如用户点击分页按钮切换页码等操作会调用 `getList` 方法来获取对应页码的数据列表 -->
<pagination v-if="count > 0" :total="count" v-model:page="queryParams.current" v-model:limit="queryParams.size"
@pagination="getList" />
if (pos - pre_pos != 0 && end - pos > 3) {
//console.log("set end video.currentTime pos=" + pos + ",start=" + start + ",end=" + end);
video.currentTime = end;
}
<!-- 添加或修改对话框部分使用 `el-dialog` 组件创建一个对话框设置对话框的标题为修改用户通过 `v-model` 指令进行双向数据绑定绑定的是 `update` 变量用于控制对话框的显示和隐藏状态`true` 表示显示`false` 表示隐藏设置对话框宽度为 500px`append-to-body` 属性设置将对话框挂载到 `body` 元素下这样可以避免一些样式或层级相关的问题常用于对话框等弹出层的显示 -->
<el-dialog title="修改用户" v-model="update" width="500px" append-to-body">
<!-- `el-form` 组件用于创建表单通过 `ref` 指令绑定表单实例的引用到 `userFormRef`方便后续在脚本中通过这个引用来操作表单比如进行表单验证等操作`label-width` 属性设置表单标签的宽度为 100px`:model` 指令绑定表单数据对象为 `userForm``:rules` 属性绑定表单验证规则为 `rules`用于整体表单的布局数据绑定以及验证相关的操作 -->
<el-form ref="userFormRef" label-width="100px" :model="userForm" :rules="rules">
<!-- 昵称表单项的定义使用 `el-form-item` 组件包裹 `el-input` 输入框`label` 属性设置该项的标签文本为昵称`prop` 属性指定该输入框对应的数据字段名为 `username`用于表单验证等相关绑定通过 `v-model` 指令双向绑定输入框的值到 `userForm.username`设置输入框宽度为 250px并添加占位提示文字引导用户输入内容 -->
<el-form-item label="昵称" prop="username">
<el-input placeholder="请输入昵称" v-model="userForm.username" style="width: 250px;" />
</el-form-item>
<!-- 角色表单项的定义和上面类似通过 `el-form-item` 包裹 `el-input`绑定到 `userForm.grade`用于输入角色相关信息不过这里从业务逻辑上看可能更适合用下拉框等选择组件来选择角色目前只是简单的文本输入框形式可能需要根据实际情况调整 -->
<el-form-item label="角色" prop="grade">
<el-input placeholder="请输入角色" v-model="userForm.grade" style="width: 250px;" />
</el-form-item>
<!-- 邮箱表单项的定义绑定到 `userForm.email`用于输入邮箱相关信息 -->
<el-form-item label="邮箱" prop="email">
<el-input placeholder="请输入email" v-model="userForm.email" style="width: 250px;" />
</el-form-item>
</el-form>
<!-- 对话框底部区域通过具名插槽 `#footer` 来自定义底部的按钮等内容这里放置了两个按钮分别是确定取消按钮点击确定按钮会触发 `submitForm` 方法来提交表单数据点击取消按钮则会将 `update` 变量设置为 `false`从而隐藏对话框取消当前的添加或修改操作 -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="update = false"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
// 从 `@/api/user` 文件中导入多个与用户相关的函数,这些函数分别用于获取用户列表、获取用户角色列表、更新用户信息以及更新用户状态等操作,它们与后端接口进行交互来实现相应的功能
import { getUserList, getUserRoleList, updateUser, updateUserStatus } from '@/api/user';
// 从 `@/api/user/types` 文件中导入多个与用户相关的类型定义,这些类型定义明确了函数参数和返回值等的数据结构,方便在代码中进行类型检查和操作,确保数据的准确性和一致性
import { User, UserForm, UserQuery, UserRole } from '@/api/user/types';
// 从 `@/utils/date` 文件中导入 `formatDate` 函数,该函数可能用于对日期相关的数据进行格式化处理(不过在当前代码中未看到实际使用的地方,可能是预留的功能或者在其他相关部分会用到)
import { formatDate } from "@/utils/date";
// 从 `@/utils/modal` 文件中导入 `messageConfirm` 和 `notifySuccess` 函数,这两个函数可能是用于弹出确认框和显示成功通知的功能,比如在执行某些重要操作前弹出确认提示,或者操作成功后显示成功消息给用户
import { messageConfirm, notifySuccess } from '@/utils/modal';
// 从 `element-plus` 中导入 `FormInstance`(表单实例类型)和 `FormRules`(表单验证规则类型),用于类型定义,使代码在处理表单相关操作时更具类型安全性,明确操作的对象和数据结构要求
import { FormInstance, FormRules } from 'element-plus';
// 从 `vue` 中导入生命周期钩子函数 `onMounted`(在组件挂载完成后执行相关逻辑)、响应式对象创建函数 `reactive`、响应式引用创建函数 `ref` 以及 `toRefs`(用于将响应式对象的属性转换为响应式引用)函数,用于处理组件中的数据响应式相关逻辑,方便数据的绑定、更新和操作
import { onMounted, reactive, ref, toRefs } from 'vue';
for (let i = 0; i < video.buffered.length - 1; i++) {
let prestart = video.buffered.start(i);
let preend = video.buffered.end(i);
if(!sourcebuffer.updating) {
sourcebuffer.remove(prestart, preend);
}
}
// 创建一个响应式引用 `userFormRef`,用于获取 `el-form` 表单(在对话框中的表单)的实例,方便后续进行表单验证等操作,初始值为 `undefined`,后续会在组件渲染后被赋值
const userFormRef = ref<FormInstance>();
if(pos - start > 10 && !sourcebuffer.updating) {
//console.warn("remove start pos=" + pos + ",start=" + start + ",end=" + end);
sourcebuffer.remove(0, pos - 3);
}
// 创建一个响应式对象 `rules`,用于定义表单验证规则,遵循 `FormRules` 类型规范,目前只定义了两个字段的验证规则:
// 对于 `username` 字段,设置了必填验证规则,当输入框失去焦点(`trigger: "blur"`)时,如果未输入内容,会弹出提示消息“请输入昵称”。
// 对于 `roleIdList` 字段(虽然在当前表单中看起来没有直接对应使用的地方,可能是复用的规则或者后续会添加相关逻辑),设置了必填验证规则,当点击(`trigger: "click"`)相关元素时,如果为空,会弹出提示消息“角色不能为空”。
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入昵称", trigger: "blur" }],
roleIdList: [{ required: true, message: "角色不能为空", trigger: "click" }]
});
if(end - pos > 10 && !sourcebuffer.updating) {
//console.warn("remove end pos=" + pos + ",start=" + start + ",end=" + end);
sourcebuffer.remove(0, end - 3);
}
}
pre_pos = pos;
}
}
}.bind(this);
// 创建一个响应式对象 `data`,用于存储页面中的各种数据和状态信息,以下是各个属性的含义:
const data = reactive({
// 用于记录总的数据条数,在分页等相关逻辑中会用到,初始值为 0后续会根据从后端获取到的数据进行更新
count: 0,
// 用于控制添加或修改对话框的显示隐藏状态,初始值为 `false`,表示对话框初始是隐藏的,当需要打开对话框进行操作时会设置为 `true`
update: false,
// 用于控制页面中表格、按钮等元素是否显示加载状态,初始值为 `false`,在发起数据请求(如获取用户列表等操作)时设置为 `true`,请求完成后再根据情况重置为 `false`
loading: false,
// 用于存储查询参数,包含当前页码和每页显示条数等信息,初始设置了默认值,类型遵循 `UserQuery` 类型规范(具体结构取决于定义),在搜索、分页等操作时会更新这些参数用于获取对应的数据
queryParams: {
current: 1,
size: 10,
} as UserQuery,
// 定义了一个类型列表不过从当前使用情况来看不太明确其具体用途可能是用于后续扩展的一些类型选择相关功能比如选择不同类型的联系方式之类的里面包含了不同的值和对应的标签如邮箱、QQ、Gitee、Github 等选项
typeList: [
{
value: 1,
label: "邮箱",
},
{
value: 2,
label: "QQ",
},
{
value: 3,
label: "Gitee",
},
{
value: 4,
label: "Github",
},
],
// 用于存储用户列表数据,是一个数组类型,里面存放的元素遵循 `User` 类型规范,初始值为空数组,后续会通过调用接口获取数据并赋值
userList: [] as User[],
// 用于绑定添加或修改对话框中的表单数据,初始值为空对象,遵循 `UserForm` 类型规范,用户在对话框表单中输入或修改的数据会实时更新到这个对象中
userForm: {} as UserForm,
// 用于存储用户角色列表数据(目前代码中未看到获取和使用该列表的完整逻辑,可能是部分功能待完善),是一个数组类型,遵循 `UserRole` 类型规范,初始值为空数组
userRoleList: [] as UserRole[],
// 用于存储角色相关的 ID 列表(同样可能是后续功能需要使用到的,目前代码中相关逻辑不太完整),是一个数组类型,元素为字符串,初始值为空数组
roleIdList: [] as string[],
});
this.ws.onmessage = function(e) {
if(firstMessage) {
firstMessage = false;
let moov = e.data;
let mp4Box = new MP4Box;
mp4Box.onReady = demux_moov;
moov.fileStart = 0;
mp4Box.appendBuffer(moov);
}
this.frameQueue.push(e.data);
if (!sourcebuffer || sourcebuffer.updating) {
return;
}
if(this.frameQueue.length === 1) {
sourcebuffer.appendBuffer(this.frameQueue.shift());
} else {
let byte_length = 0;
for (const qnode of this.frameQueue) {
byte_length += qnode.byteLength;
}
let mp4buf = new Uint8Array(byte_length);
let offset = 0;
for (const qnode of this.frameQueue) {
let frame = new Uint8Array(qnode);
mp4buf.set(frame, offset);
offset += qnode.byteLength;
}
sourcebuffer.appendBuffer(mp4buf);
this.frameQueue.splice(0, this.frameQueue.length);
}
}.bind(this);
}
// 通过 `toRefs` 函数将 `data` 对象的各个属性转换为响应式引用,并进行解构赋值,方便后续在代码中直接使用这些属性,同时保持它们的响应式特性,即数据变化时相关的 UI 会自动更新
const {
count,
update,
loading,
queryParams,
typeList,
userList,
userForm,
userRoleList,
roleIdList,
} = toRefs(data);
wsPlayer.prototype.closed = function () {
this.ws.close();
}
// 定义 `openModel` 方法,用于打开添加或修改用户的对话框,并初始化对话框中的表单数据,接收一个 `User` 类型的参数 `user`,表示当前要编辑的用户数据对象
const openModel = (user: User) => {
// 先清空 `roleIdList` 数组(可能用于重新选择角色相关的逻辑,目前不太明确其完整用途)
roleIdList.value = [];
// 将传入的用户数据对象中的 `id` 属性值赋给 `userForm.value.id`,用于在对话框表单中显示当前要编辑用户的 ID
userForm.value.id = user.id;
// 同理,将用户的昵称、角色、邮箱等属性值分别赋给 `userForm

@ -1,36 +1,41 @@
<template>
<!-- 整个页面的最外层容器添加类名 `app-container`用于后续通过样式类来统一设置页面整体样式 -->
<div class="app-container">
<!-- 搜索栏 -->
<!-- 搜索栏部分使用 `el-form` 组件创建一个内联表单方便用户输入搜索关键词并执行搜索操作 -->
<el-form :model="queryParams" :inline="true">
<!-- `el-form-item` 组件用于包裹表单中的每一项输入框这里展示的是用户昵称输入框相关部分`label` 属性用于设置该项在表单中的标签文字 -->
<el-form-item label="用户昵称">
<!-- `el-input` 组件用于创建文本输入框通过 `v-model` 双向绑定数据到 `queryParams.keyword`意味着用户在输入框中输入的内容会实时更新到 `queryParams.keyword` 反之亦然设置输入框宽度为 200px添加占位提示文字引导用户输入并且设置为可清空内容的样式同时监听键盘回车键按下事件`@keyup.enter`触发 `handleQuery` 方法来执行搜索操作 -->
<el-input @keyup.enter="handleQuery" v-model="queryParams.keyword" style="width: 200px" placeholder="请输入用户昵称"
clearable />
</el-form-item>
<el-form-item>
<!-- `el-button` 组件用于创建搜索按钮按钮类型为 `primary`通常在页面中作为主要操作按钮会有比较突出的样式效果比如颜色等方面添加了 `Search` 图标增强可视化效果点击按钮时触发 `handleQuery` 方法来执行搜索逻辑 -->
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
</el-form-item>
</el-form>
<!-- 表格展示 -->
<!-- 表格展示部分使用 `el-table` 组件展示用户相关的数据列表`border` 属性设置为显示表格边框使其看起来更清晰`:data` 属性绑定了 `userList` 数据这个数据应该是一个数组里面存放着要展示的用户相关信息`v-loading` 属性绑定了 `loading` 变量用于控制表格是否显示加载中的状态比如在数据加载过程中显示加载动画等 -->
<el-table border :data="userList" v-loading="loading">
<!-- id -->
<!-- 用户ID列的定义通过 `prop` 属性指定该列对应的数据字段名为 `id`即表格这一列展示的数据是从每行数据对象中的 `id` 属性获取的`label` 属性设置该列的标题为用户ID`align` 属性设置列内容在单元格中居中对齐`width` 属性设置该列宽度为 100px -->
<el-table-column prop="id" label="用户ID" align="center" width="100"></el-table-column>
<!-- 用户头像 -->
<!-- 用户头像列的定义通过 `prop` 属性指定对应的数据字段为 `avatar`设置列标题为头像以及内容居中对齐宽度为 100px同时通过具名插槽 `#default` 来自定义该列单元格内容的显示方式这里使用 `img` 标签展示头像图片通过 `:src` 绑定头像的地址从每行数据对象的 `avatar` 属性获取并设置图片的宽度和高度为 40px -->
<el-table-column prop="avatar" label="头像" align="center" width="100">
<template #default="scope">
<img :src="scope.row.avatar" width="40" height="40" />
</template>
</el-table-column>
<!-- 昵称 -->
<!-- 用户昵称列的定义和前面类似指定对应的数据字段为 `username`设置列标题内容对齐方式以及宽度等属性用于展示用户的昵称信息 -->
<el-table-column prop="username" label="用户昵称" align="center" width="200"></el-table-column>
<!-- 用户角色 -->
<!-- 用户角色列的定义通过 `prop` 属性指定对应的数据字段为 `grade`设置列标题为用户角色以及内容居中对齐不过目前该列的单元格内容展示部分没有具体设置可能后续需要添加相应的逻辑来展示角色相关信息 -->
<el-table-column prop="grade" label="用户角色" align="center">
</el-table-column>
<!-- 邮箱列的定义通过 `prop` 属性指定对应的数据字段为 `email`设置列标题为邮箱以及内容居中对齐同样目前该列的单元格内容展示部分没有进一步细化可能根据实际需求补充显示邮箱内容等逻辑 -->
<el-table-column prop="email" label="邮箱" align="center">
</el-table-column>
<!-- 操作 -->
<!-- 操作列的定义设置列标题为操作内容在单元格中居中对齐宽度为 100px通过具名插槽 `#default` 自定义该列单元格内容这里放置了一个编辑按钮点击按钮会触发 `openModel` 方法传入当前行的数据通过 `scope.row` 获取用于对每行数据进行相应的编辑操作 -->
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button type="primary" icon="Edit" link @click="openModel(scope.row)">
@ -39,27 +44,29 @@
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<!-- 分页组件部分引入自定义的 `pagination` 组件应该是用于实现分页功能的一个通用组件通过 `v-if` 指令根据 `count` 的值来判断是否显示该分页组件只有当 `count > 0`即有数据总条数大于 0表示有数据可分页时才会显示`:total` 属性设置总的数据条数通过 `v-model:page` `v-model:limit` 分别进行双向数据绑定绑定的是 `queryParams` 中的 `current`当前页码 `size`每页显示条数属性意味着页面和组件之间可以相互传递和更新这些分页相关的数据同时监听 `@pagination` 事件当该事件被触发时比如用户点击分页按钮切换页码等操作会调用 `getList` 方法来获取对应页码的数据列表 -->
<pagination v-if="count > 0" :total="count" v-model:page="queryParams.current" v-model:limit="queryParams.size"
@pagination="getList" />
<!-- 添加或修改对话框 -->
<el-dialog title="修改用户" v-model="update" width="500px" append-to-body>
<!-- 添加或修改对话框部分使用 `el-dialog` 组件创建一个对话框设置对话框的标题为修改用户通过 `v-model` 指令进行双向数据绑定绑定的是 `update` 变量用于控制对话框的显示和隐藏状态`true` 表示显示`false` 表示隐藏设置对话框宽度为 500px`append-to-body` 属性设置将对话框挂载到 `body` 元素下这样可以避免一些样式或层级相关的问题常用于对话框等弹出层的显示 -->
<el-dialog title="修改用户" v-model="update" width="500px" append-to-body">
<!-- `el-form` 组件用于创建表单通过 `ref` 指令绑定表单实例的引用到 `userFormRef`方便后续在脚本中通过这个引用来操作表单比如进行表单验证等操作`label-width` 属性设置表单标签的宽度为 100px`:model` 指令绑定表单数据对象为 `userForm``:rules` 属性绑定表单验证规则为 `rules`用于整体表单的布局数据绑定以及验证相关的操作 -->
<el-form ref="userFormRef" label-width="100px" :model="userForm" :rules="rules">
<!-- 昵称表单项的定义使用 `el-form-item` 组件包裹 `el-input` 输入框`label` 属性设置该项的标签文本为昵称`prop` 属性指定该输入框对应的数据字段名为 `username`用于表单验证等相关绑定通过 `v-model` 指令双向绑定输入框的值到 `userForm.username`设置输入框宽度为 250px并添加占位提示文字引导用户输入内容 -->
<el-form-item label="昵称" prop="username">
<el-input placeholder="请输入昵称" v-model="userForm.username" style="width: 250px;" />
</el-form-item>
<!-- 角色表单项的定义和上面类似通过 `el-form-item` 包裹 `el-input`绑定到 `userForm.grade`用于输入角色相关信息不过这里从业务逻辑上看可能更适合用下拉框等选择组件来选择角色目前只是简单的文本输入框形式可能需要根据实际情况调整 -->
<el-form-item label="角色" prop="grade">
<el-input placeholder="请输入角色" v-model="userForm.grade" style="width: 250px;" />
</el-form-item>
<!-- 邮箱表单项的定义绑定到 `userForm.email`用于输入邮箱相关信息 -->
<el-form-item label="邮箱" prop="email">
<el-input placeholder="请输入email" v-model="userForm.email" style="width: 250px;" />
</el-form-item>
</el-form>
<!-- 对话框底部区域通过具名插槽 `#footer` 来自定义底部的按钮等内容这里放置了两个按钮分别是确定取消按钮点击确定按钮会触发 `submitForm` 方法来提交表单数据点击取消按钮则会将 `update` 变量设置为 `false`从而隐藏对话框取消当前的添加或修改操作 -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@ -68,102 +75,4 @@
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { getUserList, getUserRoleList, updateUser, updateUserStatus } from '@/api/user';
import { User, UserForm, UserQuery, UserRole } from '@/api/user/types';
import { formatDate } from "@/utils/date";
import { messageConfirm, notifySuccess } from '@/utils/modal';
import { FormInstance, FormRules } from 'element-plus';
import { onMounted, reactive, ref, toRefs } from 'vue';
const userFormRef = ref<FormInstance>();
const rules = reactive<FormRules>({
username: [{ required: true, message: "请输入昵称", trigger: "blur" }],
roleIdList: [{ required: true, message: "角色不能为空", trigger: "click" }]
});
const data = reactive({
count: 0,
update: false,
loading: false,
queryParams: {
current: 1,
size: 10,
} as UserQuery,
typeList: [
{
value: 1,
label: "邮箱",
},
{
value: 2,
label: "QQ",
},
{
value: 3,
label: "Gitee",
},
{
value: 4,
label: "Github",
},
],
userList: [] as User[],
userForm: {} as UserForm,
userRoleList: [] as UserRole[],
roleIdList: [] as string[],
});
const {
count,
update,
loading,
queryParams,
typeList,
userList,
userForm,
userRoleList,
roleIdList,
} = toRefs(data);
const openModel = (user: User) => {
roleIdList.value = [];
userForm.value.id = user.id;
userForm.value.username = user.username;
userForm.value.grade = user.grade;
userForm.value.email = user.email;
userFormRef.value?.clearValidate();
update.value = true;
};
const submitForm = () => {
userFormRef.value?.validate((valid) => {
if (valid) {
updateUser(userForm.value).then(({ data }) => {
if (data.flag) {
notifySuccess(data.msg);
getList();
}
update.value = false;
})
}
})
};
const getList = () => {
loading.value = true;
getUserList(queryParams.value.current).then(({ data }) => {
console.log(data)
userList.value = data.data;
loading.value = false;
})
};
//
const handleQuery = () => {
queryParams.value.current = 1;
// getList();
};
onMounted(() => {
getList();
});
</script>
<style scoped></style>
</template>

@ -35,6 +35,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# 主窗口向yolo实例发送执行信号
main2yolo_begin_sgl = Signal()
# 主函数
def __init__(self, parent=None):
super(MainWindow, self).__init__()

@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
blog
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,6 @@
# Vue 3 + TypeScript + Vite
1、npm install
2、npm run dev

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<!-- 该部分包含了一些关于HTML文档的元数据和资源引用并不直接在页面上展示内容。 -->
<head>
<meta charset="UTF-8" />
<!-- 设置浏览器标签栏的网站图标。 -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<!-- 设置移动设备的视口尺寸,使页面在不同设备上呈现一致。 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MTAS系统</title>
<!-- 引入外部CSS文件用于样式定义。引入外部JavaScript文件用于实现点击特定功能。 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" />
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js"></script>
<!-- 引入APlayer外部样式文件用于音乐播放器的样式。引入APlayer外部脚本文件用于实现音乐播放器的功能。引入Meting外部脚本文件用于音乐播放器的数据加载。 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" />
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<!-- 一个使用CSS样式设置的全屏画布用于绘制烟花效果。 -->
<canvas class="fireworks"
style="position: fixed; top: 0px; left: 0px; pointer-events: none; z-index: 9999999;"></canvas>
<!-- 引入外部脚本文件,用于实现烟花效果。 -->
<script src="https://static.ttkwsd.top/config/fireworks.min.js"></script>
</body>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</html>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,53 @@
{
"name": "yolov8-vue3",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"description": "基于yolov8的车流识别项目",
"dependencies": {
"@kangc/v-md-editor": "^2.3.15",
"@vueuse/core": "^9.5.0",
"axios": "^1.3.0",
"dayjs": "^1.11.7",
"easy-typer-js": "^2.1.0",
"echarts": "^5.4.1",
"element-plus": "^2.3.7",
"js-cookie": "^3.0.1",
"nprogress": "^0.2.0",
"pinia": "^2.0.25",
"pinia-plugin-persistedstate": "^2.4.0",
"prismjs": "^1.29.0",
"swiper": "^8.4.5",
"tocbot": "^4.20.0",
"v-viewer": "^3.0.11",
"vue": "^3.2.41",
"vue-cropper": "^1.0.5",
"vue-router": "^4.0.12",
"vue3-danmaku": "^1.2.0",
"vue3-lazy": "^1.0.0-alpha.1",
"vue3-social-share": "^0.1.7"
},
"devDependencies": {
"@types/js-cookie": "^3.0.2",
"@types/node": "^18.11.9",
"@types/nprogress": "^0.2.0",
"@types/prismjs": "^1.26.0",
"@vicons/ionicons5": "^0.12.0",
"@vitejs/plugin-vue": "^3.2.0",
"naive-ui": "^2.34.3",
"sass": "^1.56.1",
"sass-loader": "^13.2.0",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.12.1",
"unplugin-vue-components": "^0.22.12",
"vite": "^3.2.3",
"vite-plugin-prismjs": "0.0.8",
"vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^1.0.9"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -0,0 +1,50 @@
<template style="height=100px;">
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="route.path" />
</keep-alive>
</router-view>
</template>
<script setup lang="ts">
// import { getBlogInfo, report } from "@/api/blogInfo";
import useStore from '@/store';
const { user } = useStore();
onMounted(() => {
console.log(
"%c AI系统 %c By pan %c",
"background:#e9546b ; padding: 1px; border-radius: 3px 0 0 3px; color: #fff; padding:5px 0;",
"background:#ec8c69 ; padding: 1px; border-radius: 0 3px 3px 0; color: #000; padding:5px 0;",
"background:transparent"
);
//
// getBlogInfo().then(({ data }) => {
// blog.setBlogInfo(data.data);
// });
// 访
// report();
})
</script>
<style scoped>
/* 最短距离——320px */
.app-wrapper {
position: relative;
min-height: 100vh;
min-width: 320px;
}
.main-wrapper {
display: flex;
flex-direction: column;
width: 100%;
padding: 0 0 8rem;
}
</style>

@ -0,0 +1,27 @@
import { Result } from "@/models/index";
import request from "@/utils/request";
import { AxiosPromise } from "axios";
import { LoginForm } from "./types";
/**
*
* @param data
* @returns Token
*/
export function login(data: LoginForm): AxiosPromise<Result<any>> {
return request({
url: "/login",
method: "post",
data,
});
}
/**
* 退
*/
export function logout(): AxiosPromise<Result<null>> {
return request({
url: "/logOut",
method: "get",
});
}

@ -0,0 +1,13 @@
/**
*
*/
export interface LoginForm {
/**
*
*/
username: string;
/**
*
*/
password: string;
}

@ -0,0 +1,6 @@
@font-face {
font-family: "Fredericka the Great";
src: url("FREDERICKATHEGREAT-REGULAR-2.TTF") format('truetype');
font-weight: normal;
font-style: normal;
}

@ -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="1669617705240" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2243" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M883.4 163.2H136.7c-40.5 0-72.8 24.9-72.8 55.6v583.9c0 31.9 33.3 57.9 74 57.9h751.2c35.5 3.4 67.2-22.4 71-57.9V218.8c0-30.7-34.5-55.6-77.1-55.6h0.4zM358.9 293.4c40.7-0.1 73.9 32.8 74 73.5 0.1 40.7-32.8 73.9-73.5 74s-73.9-32.8-74-73.5v-0.2c0-40.7 32.9-73.6 73.5-73.8z m457 483.8H209.5c-23.5 0-28.2-13.6-12.4-29.8l130.1-136.9c16.7-16.5 42.7-19 62.2-5.9l95.8 67.6c19.2 13.3 45.3 9.8 60.4-8l221.9-268.9c14.6-17.6 29.1-13.6 32.4 8.5l50.7 334c2.9 18.7-10 36.2-28.7 39.1-1.9 0.3-4 0.4-6 0.3z" fill="" p-id="2244"></path></svg>

After

Width:  |  Height:  |  Size: 852 B

@ -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="1674384686650" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16276" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M319.4 478l272-272c18.8-18.8 49.2-18.8 67.8 0l45.2 45.2c18.8 18.8 18.8 49.2 0 67.8L511.8 512l192.8 192.8c18.8 18.8 18.8 49.2 0 67.8L659.4 818c-18.8 18.8-49.2 18.8-67.8 0l-272-272c-19-18.8-19-49.2-0.2-68z" p-id="16277"></path></svg>

After

Width:  |  Height:  |  Size: 565 B

@ -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="1674384675644" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15358" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M704.6 546l-272 272c-18.8 18.8-49.2 18.8-67.8 0l-45.2-45.2c-18.8-18.8-18.8-49.2 0-67.8l192.8-192.8-192.8-192.8c-18.8-18.8-18.8-49.2 0-67.8L364.6 206c18.8-18.8 49.2-18.8 67.8 0l272 272c19 18.8 19 49.2 0.2 68z" p-id="15359"></path></svg>

After

Width:  |  Height:  |  Size: 569 B

@ -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="1669164213537" class="icon" viewBox="0 0 1092 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2201" xmlns:xlink="http://www.w3.org/1999/xlink" width="213.28125" height="200"><path d="M921.463467 307.746133a109.226667 109.226667 0 0 1 109.226666 109.226667v477.866667a109.226667 109.226667 0 0 1-109.226666 109.226666h-750.933334a109.226667 109.226667 0 0 1-109.226666-109.226666v-477.866667a109.226667 109.226667 0 0 1 109.226666-109.226667z m0 81.92h-750.933334a27.306667 27.306667 0 0 0-27.306666 27.306667v477.866667c0 15.018667 12.219733 27.306667 27.306666 27.306666h750.933334a27.306667 27.306667 0 0 0 27.306666-27.306666v-477.866667a27.306667 27.306667 0 0 0-27.306666-27.306667zM781.9264 507.221333c7.304533 12.4928-10.513067 35.293867-10.513067 35.293867l-245.077333 284.808533a42.5984 42.5984 0 0 1-58.9824 6.485334s-112.8448-137.216-116.736-142.472534c-11.127467-17.8176-24.1664-28.740267-23.825067-49.834666 0.477867-13.653333 17.749333-22.7328 17.749334-22.7328 35.908267-3.140267 93.525333 47.240533 137.4208 81.237333 10.581333 8.192 27.716267 7.509333 36.590933-1.8432 52.770133-50.449067 132.437333-129.706667 194.7648-188.2112 18.705067-18.295467 55.364267-28.535467 68.608-2.730667z m64.443733-363.178666a40.96 40.96 0 1 1 0 81.92h-600.746666a40.96 40.96 0 1 1 0-81.92h600.746666z m-136.533333-136.533334a40.96 40.96 0 1 1 0 81.92h-327.68a40.96 40.96 0 1 1 0-81.92h327.68z" p-id="2202"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -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="1674380453047" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3843" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M448 789.312V0h128v789.312l234.688-234.624L896 640l-384 384-384-384 85.312-85.312L448 789.312z" fill="#373D41" p-id="3844"></path></svg>

After

Width:  |  Height:  |  Size: 469 B

@ -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="1674380457262" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3998" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M576 234.688V1024H448V234.688L213.312 469.312 128 384l384-384 384 384-85.312 85.312L576 234.688z" fill="#373D41" p-id="3999"></path></svg>

After

Width:  |  Height:  |  Size: 471 B

@ -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="1669164322759" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2355" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M928 608C928 572.64 899.36 544 864 544 792.96 544 679.04 544 608 544 572.64 544 544 572.64 544 608 544 679.04 544 792.96 544 864 544 899.36 572.64 928 608 928 679.04 928 792.96 928 864 928 899.36 928 928 899.36 928 864 928 792.96 928 679.04 928 608ZM480 608C480 572.64 451.36 544 416 544 344.96 544 231.04 544 160 544 124.64 544 96 572.64 96 608 96 679.04 96 792.96 96 864 96 899.36 124.64 928 160 928 231.04 928 344.96 928 416 928 451.36 928 480 899.36 480 864 480 792.96 480 679.04 480 608ZM480 160C480 124.64 451.36 96 416 96 344.96 96 231.04 96 160 96 124.64 96 96 124.64 96 160 96 231.04 96 344.96 96 416 96 451.36 124.64 480 160 480 231.04 480 344.96 480 416 480 451.36 480 480 451.36 480 416 480 344.96 480 231.04 480 160ZM928 160C928 124.64 899.36 96 864 96 792.96 96 679.04 96 608 96 572.64 96 544 124.64 544 160 544 231.04 544 344.96 544 416 544 451.36 572.64 480 608 480 679.04 480 792.96 480 864 480 899.36 480 928 451.36 928 416 928 344.96 928 231.04 928 160Z" p-id="2356"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -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="1675158031897" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2375" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M675.328 117.717333a21.333333 21.333333 0 0 1-16.341333 39.402667A382.762667 382.762667 0 0 0 512 128C299.925333 128 128 299.925333 128 512s171.925333 384 384 384 384-171.925333 384-384c0-51.114667-9.984-100.8-29.12-146.986667a21.333333 21.333333 0 0 1 39.402667-16.341333A425.429333 425.429333 0 0 1 938.666667 512c0 235.648-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333c56.746667 0 112 11.093333 163.328 32.384z m-170.88 281.152a21.290667 21.290667 0 0 1 0.042667-30.208l82.986666-82.986666a63.850667 63.850667 0 0 1 90.432 0.021333l60.373334 60.394667a63.914667 63.914667 0 0 1 0.064 90.410666l-150.997334 150.997334a63.829333 63.829333 0 0 1-90.410666-0.042667l-30.229334-30.229333a21.269333 21.269333 0 0 1 0-30.165334 21.290667 21.290667 0 0 1 30.186667 0l30.208 30.229334a21.162667 21.162667 0 0 0 30.08 0.042666l150.997333-150.997333a21.248 21.248 0 0 0-0.042666-30.08l-60.394667-60.373333a21.184 21.184 0 0 0-30.101333-0.021334l-82.986667 82.986667a21.333333 21.333333 0 0 1-30.208 0z m15.104 226.261334a21.290667 21.290667 0 0 1-0.042667 30.208l-82.986666 82.986666a63.850667 63.850667 0 0 1-90.432-0.021333l-60.373334-60.394667a63.914667 63.914667 0 0 1-0.064-90.410666l150.997334-150.997334a63.829333 63.829333 0 0 1 90.410666 0.042667l30.229334 30.229333a21.269333 21.269333 0 0 1 0 30.165334 21.290667 21.290667 0 0 1-30.186667 0l-30.208-30.229334a21.162667 21.162667 0 0 0-30.08-0.042666l-150.997333 150.997333a21.248 21.248 0 0 0 0.042666 30.08l60.394667 60.373333a21.184 21.184 0 0 0 30.101333 0.021334l82.986667-82.986667a21.333333 21.333333 0 0 1 30.208 0z" fill="#3D3D3D" p-id="2376"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -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="1675158073131" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2529" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 42.666667a32 32 0 0 1 0 64C288.149333 106.666667 106.666667 288.149333 106.666667 512s181.482667 405.333333 405.333333 405.333333 405.333333-181.482667 405.333333-405.333333a32 32 0 0 1 64 0c0 259.2-210.133333 469.333333-469.333333 469.333333S42.666667 771.2 42.666667 512 252.8 42.666667 512 42.666667z m233.685333 119.466666l2.282667 2.069334 90.496 90.496a32 32 0 0 1 2.090667 42.986666l-2.090667 2.282667-90.496 90.496a32 32 0 0 1-47.338667-42.965333l2.069334-2.282667 35.882666-35.882667H661.333333a138.666667 138.666667 0 0 0-138.581333 133.696L522.666667 448v128a32 32 0 0 1-63.850667 3.072L458.666667 576v-128a202.666667 202.666667 0 0 1 196.906666-202.581333L661.333333 245.333333h77.248l-35.882666-35.882666a32 32 0 0 1-2.069334-42.965334l2.069334-2.282666a32 32 0 0 1 42.986666-2.090667z" fill="#131415" p-id="2530"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -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="1675157966649" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2221" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M513.457231 41.353846c-133.377969 2.837662-244.999877 49.189415-332.973292 137.160862C92.512492 266.488123 46.160738 378.110031 43.323077 511.488c2.837662 133.377969 49.189415 244.054646 137.160862 332.026092C268.457354 931.487508 380.079262 977.839262 513.457231 980.676923c133.377969-2.837662 244.054646-49.189415 332.026092-137.160862S979.808492 644.867938 982.646154 511.488c-2.837662-133.377969-49.189415-244.054646-137.160862-332.026092C757.511877 90.543262 646.837169 44.191508 513.457231 41.353846L513.457231 41.353846zM811.431385 799.056738c-23.650462-11.352615-49.189415-23.648492-74.730338-26.486154-67.160615-5.675323-108.782277-16.080738-124.863015-32.161477-15.137477-16.082708-21.758031-38.784-18.9184-68.109785 0.945231-17.9712 5.675323-28.376615 16.080738-33.108677 10.405415-4.728123 21.756062-31.216246 33.108677-78.513231 3.784862-14.188308 7.567754-25.540923 12.297846-34.053908 4.728123-8.512985 12.295877-26.486154 21.756062-55.809969 4.730092-20.810831 4.730092-33.108677-0.945231-35.944369-5.675323-2.837662-9.460185-3.784862-10.403446-2.837662L669.538462 411.218708c2.837662-13.243077 4.728123-29.323815 6.620554-47.296985 5.677292-47.296985-3.782892-87.973415-28.378585-122.027323-24.593723-34.999138-69.998277-52.972308-137.160862-54.864738-59.594831 0.945231-90.811077 24.595692-125.810215 53.919508-38.784 30.271015-52.027077 70.945477-41.621662 122.972554 7.567754 38.784 18.9184 70.945477 11.350646 68.107815-0.945231-0.945231-4.728123 0-9.458215 2.837662-4.730092 2.837662-5.675323 15.135508-1.892431 35.944369 10.405415 25.540923 17.973169 43.514092 23.648492 52.974277 5.675323 9.458215 9.458215 21.756062 12.297846 36.8896 9.460185 46.351754 18.9184 71.892677 29.323815 76.6208 10.405415 4.730092 17.025969 17.027938 20.810831 34.999138 4.730092 29.325785-0.945231 52.027077-17.973169 68.109785-17.025969 16.080738-57.7024 26.486154-122.027323 32.161477-23.648492 2.837662-52.027077 14.188308-74.728369 25.540923-72.837908-75.675569-115.4048-175.946831-116.352-286.621538 2.837662-117.297231 43.514092-214.728862 122.027323-293.244062s175.946831-119.187692 293.244062-122.027323c117.295262 2.837662 214.728862 43.514092 292.296862 122.027323 78.513231 78.513231 119.189662 175.946831 122.027323 293.244062C926.834215 624.055138 884.267323 724.324431 811.431385 799.056738z" p-id="2222"></path></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -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="1674441926816" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6952" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1024 512c0-75.4-47.4-139.8-114.2-164.8 29.4-64.8 17.6-143.8-35.8-197.2-53.4-53.4-132.4-65.2-197.2-35.8C651.8 47.4 587.4 0 512 0s-139.8 47.4-164.8 114.2c-64.8-29.4-144-17.6-197.2 35.8-53.4 53.4-65.2 132.4-35.8 197.2C47.4 372.2 0 436.6 0 512s47.4 139.8 114.2 164.8c-29.4 64.8-17.6 144 35.8 197.2 53.2 53.2 132.2 65.4 197.2 35.8 25 66.6 89.4 114.2 164.8 114.2s139.8-47.4 164.8-114.2c65.2 29.6 144 17.4 197.2-35.8 53.4-53.4 65.2-132.4 35.8-197.2 66.8-25 114.2-89.4 114.2-164.8z m-289.6-88.5L472.32 683.48c-8.62 8.56-22.56 8.5-31.1-0.12l-151.44-152.66c-8.56-8.62-8.5-22.56 0.12-31.12l52.06-51.64c8.62-8.56 22.56-8.5 31.12 0.12l84.3 84.98 194.4-192.84c8.62-8.56 22.56-8.5 31.1 0.12l51.64 52.06c8.56 8.64 8.52 22.58-0.12 31.12z" p-id="6953" fill="#ea387e"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -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="1675396060001" class="icon" viewBox="0 0 1129 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2514" xmlns:xlink="http://www.w3.org/1999/xlink" width="220.5078125" height="200"><path d="M234.909 9.656a80.468 80.468 0 0 1 68.398 0 167.374 167.374 0 0 1 41.843 30.578l160.937 140.82h115.07l160.936-140.82a168.983 168.983 0 0 1 41.843-30.578A80.468 80.468 0 0 1 930.96 76.445a80.468 80.468 0 0 1-17.703 53.914 449.818 449.818 0 0 1-35.406 32.187 232.553 232.553 0 0 1-22.531 18.508h100.585a170.593 170.593 0 0 1 118.289 53.109 171.397 171.397 0 0 1 53.914 118.288v462.693a325.897 325.897 0 0 1-4.024 70.007 178.64 178.64 0 0 1-80.468 112.656 173.007 173.007 0 0 1-92.539 25.75h-738.7a341.186 341.186 0 0 1-72.421-4.024A177.835 177.835 0 0 1 28.91 939.065a172.202 172.202 0 0 1-27.36-92.539V388.662a360.498 360.498 0 0 1 0-66.789A177.03 177.03 0 0 1 162.487 178.64h105.414c-16.899-12.07-31.383-26.555-46.672-39.43a80.468 80.468 0 0 1-25.75-65.984 80.468 80.468 0 0 1 39.43-63.57M216.4 321.873a80.468 80.468 0 0 0-63.57 57.937 108.632 108.632 0 0 0 0 30.578v380.615a80.468 80.468 0 0 0 55.523 80.469 106.218 106.218 0 0 0 34.601 5.632h654.208a80.468 80.468 0 0 0 76.444-47.476 112.656 112.656 0 0 0 8.047-53.109v-354.06a135.187 135.187 0 0 0 0-38.625 80.468 80.468 0 0 0-52.304-54.719 129.554 129.554 0 0 0-49.89-7.242H254.22a268.764 268.764 0 0 0-37.82 0z m0 0" fill="#ff5ca1" p-id="2515"></path><path d="M348.369 447.404a80.468 80.468 0 0 1 55.523 18.507 80.468 80.468 0 0 1 28.164 59.547v80.468a80.468 80.468 0 0 1-16.094 51.5 80.468 80.468 0 0 1-131.968-9.656 104.609 104.609 0 0 1-10.46-54.719v-80.468a80.468 80.468 0 0 1 70.007-67.593z m416.02 0a80.468 80.468 0 0 1 86.102 75.64v80.468a94.148 94.148 0 0 1-12.07 53.11 80.468 80.468 0 0 1-132.773 0 95.757 95.757 0 0 1-12.875-57.133V519.02a80.468 80.468 0 0 1 70.007-70.812z m0 0" fill="#ff5ca1" p-id="2516"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -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="1669126963369" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2877" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M314.9 533.9h38.9c28.7 0 51.9-23.2 51.9-51.9s-23.2-51.9-51.9-51.9h-38.9c-28.7 0-51.9 23.2-51.9 51.9s23.2 51.9 51.9 51.9zM492.5 533.9h38.9c28.7 0 51.9-23.2 51.9-51.9s-23.2-51.9-51.9-51.9h-38.9c-28.7 0-51.9 23.2-51.9 51.9 0.1 28.7 23.3 51.9 51.9 51.9zM670.2 533.9h38.9c28.7 0 51.9-23.2 51.9-51.9s-23.2-51.9-51.9-51.9h-38.9c-28.7 0-51.9 23.2-51.9 51.9 0.1 28.7 23.3 51.9 51.9 51.9zM314.9 732.8h38.9c28.7 0 51.9-23.2 51.9-51.9S382.5 629 353.8 629h-38.9c-28.7 0-51.9 23.2-51.9 51.9s23.2 51.9 51.9 51.9zM492.5 732.8h38.9c28.7 0 51.9-23.2 51.9-51.9S560.1 629 531.4 629h-38.9c-28.7 0-51.9 23.2-51.9 51.9 0.1 28.7 23.3 51.9 51.9 51.9zM670.2 732.8h38.9c28.7 0 51.9-23.2 51.9-51.9S737.8 629 709.1 629h-38.9c-28.7 0-51.9 23.2-51.9 51.9 0.1 28.7 23.3 51.9 51.9 51.9z" p-id="2878"></path><path d="M875.2 150h-51.9v-25.9c0-14.3-11.6-25.9-25.9-25.9h-51.9c-14.3 0-25.9 11.6-25.9 25.9V150h-415v-25.9c0-14.3-11.6-25.9-25.9-25.9h-51.9c-14.3 0-25.9 11.6-25.9 25.9V150H149c-28.7 0-51.9 23.2-51.9 51.9v674.4c0 28.7 23.2 51.9 51.9 51.9h726.3c28.7 0 51.9-23.2 51.9-51.9V201.9c-0.2-28.6-23.4-51.9-52-51.9z m-43.9 681.5H190.7v-484h640.6v484z" p-id="2879"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -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="1669794428953" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2907" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M71.001077 234.030128c0 14.639418 6.025227 29.189809 16.375969 39.540552 10.351766 10.350742 24.902156 16.376992 39.541575 16.376992 14.644535 0 29.194926-6.02625 39.545668-16.376992 10.350742-10.350742 16.376992-24.901133 16.376992-39.540552 0-14.640442-6.02625-29.189809-16.376992-39.546691-10.350742-10.350742-24.901133-16.375969-39.545668-16.375969-14.640442 0-29.189809 6.025227-39.541575 16.375969C77.027327 204.840318 71.001077 219.390709 71.001077 234.030128L71.001077 234.030128zM71.001077 234.030128" p-id="2908"></path><path d="M63.921845 511.155772c0 14.656815 6.034437 29.221532 16.394389 39.585577 10.366092 10.359952 24.928762 16.395412 39.5866 16.395412 14.653745 0 29.221532-6.03546 39.581484-16.395412 10.364045-10.364045 16.395412-24.928762 16.395412-39.585577 0-14.653745-6.031367-29.221532-16.395412-39.582507-10.359952-10.364045-24.927739-16.394389-39.581484-16.394389-14.658861 0-29.221532 6.030343-39.5866 16.394389C69.956282 481.934241 63.921845 496.501004 63.921845 511.155772L63.921845 511.155772zM63.921845 511.155772" p-id="2909"></path><path d="M63.921845 789.69665c0 14.658861 6.034437 29.222555 16.394389 39.5866 10.366092 10.364045 24.928762 16.394389 39.5866 16.394389 14.653745 0 29.221532-6.030343 39.581484-16.394389 10.364045-10.364045 16.395412-24.928762 16.395412-39.5866 0-14.652721-6.031367-29.216415-16.395412-39.581484-10.359952-10.364045-24.927739-16.395412-39.581484-16.395412-14.658861 0-29.221532 6.031367-39.5866 16.395412C69.956282 760.480234 63.921845 775.044952 63.921845 789.69665L63.921845 789.69665zM63.921845 789.69665" p-id="2910"></path><path d="M959.306582 231.434c0 29.495778-21.88545 53.325509-48.960085 53.325509L329.898569 284.759509c-27.074635 0-49.019437-23.892153-49.019437-53.325509l0 0c0-29.437449 21.886473-53.325509 49.019437-53.325509l580.388577 0C937.421132 178.107467 959.306582 201.995527 959.306582 231.434L959.306582 231.434 959.306582 231.434zM959.306582 231.434" p-id="2911"></path><path d="M959.306582 508.622066c0 29.432333-21.88545 53.325509-48.960085 53.325509L329.898569 561.947576c-27.074635 0-49.019437-23.8942-49.019437-53.325509l0 0c0-29.496801 21.886473-53.326533 49.019437-53.326533l580.388577 0C937.421132 455.237205 959.306582 479.125265 959.306582 508.622066L959.306582 508.622066 959.306582 508.622066zM959.306582 508.622066" p-id="2912"></path><path d="M959.306582 786.988981c0 29.491685-21.88545 53.384861-48.960085 53.384861L329.898569 840.373843c-27.074635 0-49.019437-23.892153-49.019437-53.384861l0 0c0-29.379121 21.886473-53.268204 49.019437-53.268204l580.388577 0C937.421132 733.720777 959.306582 757.609861 959.306582 786.988981L959.306582 786.988981 959.306582 786.988981zM959.306582 786.988981" p-id="2913"></path></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -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="1674610046469" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26311" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 64.383234C264.7878 64.383234 64.383234 264.7878 64.383234 512s200.404567 447.616766 447.616766 447.616766 447.616766-200.404567 447.616766-447.616766S759.2122 64.383234 512 64.383234zM691.046707 601.523353 512 601.523353c-24.721118 0-44.761677-20.040559-44.761677-44.761677 0 0 0 0 0-0.001022s0 0 0-0.001022L467.238323 288.191617c0-24.721118 20.040559-44.761677 44.761677-44.761677 24.721118 0 44.761677 20.040559 44.761677 44.761677l0 223.808383 134.28503 0c24.721118 0 44.761677 20.040559 44.761677 44.761677S715.767824 601.523353 691.046707 601.523353z" p-id="26312"></path></svg>

After

Width:  |  Height:  |  Size: 922 B

@ -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="1674643469450" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4760" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M517.12 76.8c-257.536 0-465.92 180.224-465.92 402.432 0 98.816 41.472 189.952 110.08 259.584 9.728 10.24 14.848 24.064 11.776 37.888l-27.648 138.752c-3.584 18.432 16.384 32.256 32.256 22.016l128-81.408c11.264-7.168 25.088-8.192 37.376-4.096 53.76 18.944 112.64 29.184 174.08 29.184 257.536 0 465.92-180.224 465.92-402.432S774.656 76.8 517.12 76.8z m-211.968 465.92c-35.328 0-63.488-28.672-63.488-63.488s28.672-63.488 63.488-63.488S368.64 443.904 368.64 479.232 340.48 542.72 305.152 542.72z m211.968 0c-35.328 0-63.488-28.672-63.488-63.488s28.672-63.488 63.488-63.488 63.488 28.672 63.488 63.488S552.448 542.72 517.12 542.72z m211.968 0c-35.328 0-63.488-28.672-63.488-63.488s28.672-63.488 63.488-63.488c35.328 0 63.488 28.672 63.488 63.488s-28.672 63.488-63.488 63.488z" fill="#90949E" p-id="4761"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -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="1680792185810" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3469" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 144.794c-247.162 0-447.527 161.007-447.527 359.62 0 82.45 34.532 158.417 92.605 219.078l-0.264 1.396-22.58 119.482c-4.195 22.198 17.213 40.612 38.534 33.146l114.764-40.186 27.887-9.765c59.339 23.353 126.052 36.469 196.58 36.469 247.162 0 447.527-161.007 447.527-359.62S759.162 144.794 512 144.794z" p-id="3470"></path></svg>

After

Width:  |  Height:  |  Size: 662 B

@ -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="1669187491141" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5406" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.390625" height="200"><path d="M857.088 224.256q28.672-28.672 69.12-28.672t69.12 28.672q29.696 28.672 29.696 68.608t-29.696 68.608l-382.976 380.928q-12.288 14.336-30.72 19.968t-38.912 4.608-40.448-8.704-34.304-22.016l-376.832-374.784q-29.696-28.672-29.696-68.608t29.696-68.608q14.336-14.336 32.256-21.504t36.864-7.168 37.376 7.168 32.768 21.504l313.344 309.248z" p-id="5407" fill="#e6e6e6"></path></svg>

After

Width:  |  Height:  |  Size: 712 B

@ -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="1674609796006" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20215" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M541.4 212c90.9 90.8 180.4 180.1 273 272.5-3 1.8-7.6 3.5-10.8 6.7-135.5 134-271.1 267.9-405.8 402.6-17.6 17.6-36.5 28.8-60.3 35.5-92.4 26.2-184.5 53.8-276.7 80.8-20.6 6-36.7 0.6-47-15.4-6.8-10.4-6.8-22-3.5-33.4 29.5-100.8 59-201.6 88.9-302.3 2.2-7.3 6.8-14.7 12.2-20 140.5-139.3 281.2-278.4 421.8-417.5 3.1-3.1 5.7-6.6 8.2-9.5zM165.6 702.5c-1.4 4.2-2.5 7.2-3.4 10.3-12.5 42.2-23.4 85-37.9 126.5-7.6 21.6-5.5 36.9 13.4 49.7 3.5 2.4 6.5 5.7 9.1 9.1 4.1 5.4 8.7 5.5 14.8 3.7 34.5-10.4 69.2-20.5 103.8-30.7 17.3-5.1 34.6-10.1 53.2-15.6-2.9-3.3-4.5-5.9-6.7-7.5-14.2-10.3-20.6-24-19.3-41.6 0.5-6.6-0.4-13.2-0.8-19.9-1.1-18.4-2.3-36.8-3.5-55.6-25.3-2.1-49.4-4.6-73.5-5.8-17.6-0.9-34.2-2.7-45-19.1-0.6-1.1-1.9-1.7-4.2-3.5z m0 0M947.5 331.4c-86-85.8-171.8-171.6-258.5-258.2 20.9-19 37.7-43.8 65.1-57 33-15.9 74.1-8.4 103.4 20.4 42.5 41.9 84.9 83.9 126.6 126.7 38.5 39.5 37.9 92.8-0.5 132.3-12 12.4-24.4 24.2-36.1 35.8z m0 0M912.4 382.2c-19.3 18.1-39.4 36.9-59 55.2-90.2-90.2-179.8-179.8-270-269.9 19.8-18.5 39.8-37.3 58.9-55.3 90.2 90 179.8 179.6 270.1 270z m0 0" fill="" p-id="20216"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -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="1672813716691" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4568" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M872.802928 755.99406 872.864326 755.99406 872.864326 755.624646Z" fill="#272536" p-id="4569"></path><path d="M807.273469 216.727043c-162.808016-162.836669-427.736874-162.836669-590.544891 0-162.836669 162.806993-162.836669 427.736874 0 590.543867 162.808016 162.837692 427.737898 162.837692 590.544891 0C970.110137 644.462894 970.110137 379.534036 807.273469 216.727043M764.893242 764.92036c-139.444912 139.443889-366.370225 139.414213-505.798764 0-139.459239-139.473565-139.459239-366.354875 0-505.827417 139.428539-139.429563 366.354875-139.460262 505.798764 0C904.336108 398.521482 904.336108 625.476471 764.893242 764.92036" fill="#231F20" p-id="4570"></path><path d="M381.724423 468.02137c24.783453 0 44.953841-20.169365 44.953841-44.967144 0-24.828478-20.170388-45.027519-44.953841-45.027519-24.842805 0-45.013193 20.199041-45.013193 45.027519C336.71123 447.852004 356.881618 468.02137 381.724423 468.02137" fill="#231F20" p-id="4571"></path><path d="M640.680243 468.095048c24.812105 0 45.010123-20.213367 45.010123-45.01217 0-24.827455-20.198018-44.99682-45.010123-44.99682-24.785499 0-44.953841 20.169365-44.953841 44.99682C595.726401 447.88168 615.894743 468.095048 640.680243 468.095048" fill="#231F20" p-id="4572"></path><path d="M642.245901 619.058294l-2.453888 0.798179c-40.310078 18.248619-83.548858 27.5341-128.411625 27.5341-46.343491 0-90.173742-9.375531-130.305765-27.799136l-2.425236-0.741897c-1.508353-0.413416-3.548826-1.003863-6.092765-1.003863-14.757099 0-26.734898 11.977799-26.734898 26.675546 0 6.978948 3.282766 13.988596 8.695033 19.253506l-0.325411 1.62501 6.831592 3.076058c47.911196 21.679765 100.021018 33.095769 150.681838 33.095769 51.608402 0 102.180194-11.120268 150.978597-33.361829 8.575306-4.703115 13.928221-13.721513 13.928221-23.511483C676.611593 627.458615 661.027663 613.290941 642.245901 619.058294" fill="#231F20" p-id="4573"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -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="1674610370617" class="icon" viewBox="0 0 1152 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28792" xmlns:xlink="http://www.w3.org/1999/xlink" width="225" height="200"><path d="M1138.70922 463.262C1025.93922 271.898 815.62122 144 576.00122 144 336.28122 144 126.00922 271.988 13.29322 463.262a95.998 95.998 0 0 0 0 97.478C126.06322 752.102 336.38122 880 576.00122 880c239.72 0 449.992-127.988 562.708-319.262a95.994 95.994 0 0 0 0-97.476zM576.00122 784c-150.324 0-272-121.654-272-272 0-150.324 121.652-272 272-272 150.324 0 272 121.652 272 272 0 150.324-121.652 272-272 272z m208-272c0 114.876-93.124 208-208 208s-208-93.124-208-208c0-35.416 8.862-68.758 24.472-97.946l-0.002 0.064c0 47.302 38.346 85.646 85.648 85.646s85.648-38.346 85.648-85.646c0-47.302-38.346-85.648-85.648-85.648l-0.064 0.002C507.24322 312.862 540.58522 304 576.00122 304c114.876 0 208 93.124 208 208z" fill="" p-id="28793"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -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="1669544371691" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2231" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M932.9 407.3c-5.8-8.3-17.3-18.3-38.9-18.8-5.7-0.1-11.4 0.4-17.1 1.1 8.9-17.3 17.6-40.3 4.9-62.9-12-21.3-37.1-31.1-74.8-29.1-20.2 1.1-39.2 5.1-46.4 6.8-79.9 18.7-127.1 74.6-142.6 93-7.1 8.4-14 16.6-20.4 24.6 30.7-46.6 53.9-121.2 39.3-193.2-10.6-52.3-43.7-106.7-76.8-126.4-17.2-10.3-31.4-9.2-40.2-6.5-9.7 3-22.8 10.8-29.9 31.2-1.9 5.4-3.2 11-4.2 16.6-13.8-13.8-32.9-29.2-58.3-24.1-24 4.8-41.1 25.7-50.8 62.1-5.2 19.6-7.2 38.9-7.8 46.2-6.9 81.8 31.7 143.9 44.4 164.3 5.8 9.3 11.5 18.4 17.1 27-34.8-43.6-98.6-88.7-171.6-97-53.1-6-115 8.6-144 34-15.1 13.2-18.4 27-18.6 36.2-0.2 10.2 3.2 25 20.4 38.1 4.6 3.5 9.5 6.4 14.5 9.1-17.4 8.8-37.9 22.3-40.9 48-2.8 24.3 11.8 47 43.4 67.5 17 11 34.7 18.9 41.6 21.7 33.7 14.2 66.5 18.6 94.5 18.6 34.9 0 62.5-6.8 75.5-10 10.7-2.6 21.1-5.2 31-7.9-52.2 19.7-114.9 66.4-145.3 133.2-22.1 48.6-27.4 112-12.2 147.5 7.9 18.4 20 25.9 28.7 28.9 9.6 3.3 24.8 4.7 42.5-7.7 4.7-3.3 9-7 13.2-10.9 3 19.2 9.4 42.9 33 53.8 6.7 3.1 13.7 4.6 21 4.6 17.2 0 36.1-8.4 56.6-25 15.7-12.8 28.7-27.2 33.5-32.8 53.7-62.1 58.9-135.1 60.7-159 0.8-11 1.6-21.8 2-32.1 2.5 55.8 27.5 129.9 81.8 179.6 36.9 33.8 90.6 57.5 128.9 57.5 2.6 0 5.1-0.1 7.6-0.3 20-1.8 30.8-11 36.4-18.4 6.1-8.1 12.1-22.1 5.9-42.8-1.7-5.5-3.9-10.8-6.3-15.9 19.2 3.1 43.8 4.3 61.3-14.8 16.6-18 18.1-44.9 4.6-80.1-7.3-18.9-17-35.7-20.8-42-42.5-70.2-110.2-97.8-132.5-106.9-10.2-4.1-20.1-8.2-29.7-11.8 20.5 5.6 44.4 9 69.8 9 41.4 0 86.4-8.9 126.1-31.3 46.5-26.3 88-74.5 96.5-112.1 4.1-19.7-1.3-32.9-6.6-40.4zM433.7 233.4c1.4-16.5 4.6-31.8 7.9-42 1.4 1.4 2.7 2.8 3.8 3.9 6.3 6.6 12.8 13.4 20.4 19 17.9 12.9 33.6 12 43.7 9.1 10.4-3.1 24.4-11.2 32.3-32.7 1.5-4.1 2.7-8.4 3.7-12.6 1.4 1.9 2.8 4 4.2 6.2 11.2 17.6 19.6 38 23.6 57.5 11.6 56.8-10.7 122.3-37.6 155-12 14.7-20.9 18-23 18 0 0-3.8-0.4-12.3-10.1-9.7-11-20.5-28.4-31.9-46.7-10.9-17.6-39.9-64.2-34.8-124.6z m-104.1 289c-11.3 2.8-33.1 8.2-59.9 8.2-20.9 0-44.9-3.3-69.3-13.5-15.3-6.4-28.9-14.2-37.5-20.5 1.8-0.9 3.5-1.7 4.9-2.4 8.2-3.9 16.7-8 24.3-13.6 17.8-13 21.9-28.3 22.1-38.8 0.3-10.8-3.2-26.6-21.1-40.8-3.4-2.7-7.1-5.2-10.8-7.4 2.3-0.7 4.7-1.4 7.2-2.1 20.2-5.3 42.2-6.9 61.9-4.7 57.6 6.6 113 48 135.8 83.7 10.3 16 10.7 25.4 10 27.5 0 0-1.6 3.5-13.4 8.6-13.4 5.7-33.2 10.6-54.2 15.8zM443 705.3c-1.5 20.6-5.5 75.4-45 121.2-10.8 12.5-22.4 23.1-31.1 29.3-0.3-2-0.5-3.8-0.7-5.4-1.2-9-2.4-18.4-5.4-27.3-6.9-20.9-20.1-29.5-30.1-33-4.1-1.5-9.2-2.6-15-2.6-8.6 0-19 2.5-30.3 10-3.6 2.4-7.1 5.2-10.4 8 0-2.4 0.1-4.9 0.3-7.5 1.2-20.8 6.4-42.2 14.7-60.3 24.1-52.8 80.6-92.6 121.6-103.3 18.4-4.8 27.5-2.3 29.2-1 0 0 2.8 2.6 4 15.4 1.3 14.6-0.2 35-1.8 56.5z m310.4 29c8.6 14.2 15 28.4 18.3 38.6-1.9-0.3-3.8-0.7-5.4-1-8.9-1.6-18.1-3.3-27.5-3.3h-0.2c-22 0.1-34.3 10-40.7 18.4-6.6 8.6-13.1 23.4-6.9 45.4 1.2 4.2 2.7 8.4 4.4 12.3-2.2-0.8-4.6-1.6-7.1-2.6-19.4-7.6-38.2-19.2-52.9-32.6-42.8-39.2-63.2-105.3-60.7-147.5 1.1-19 6.3-26.8 8.1-28.1 0 0 1.1-0.6 4.3-0.6 2.5 0 6.2 0.4 11.6 1.6 14.3 3.2 33.2 10.9 53.3 19.1 19.2 7.8 70.1 28.5 101.4 80.3zM613.1 571.5c-10.3-2.3-41.7-9.4-68.2 9.7-20.2 14.6-32.2 40.1-34.8 74.1-0.1-4.3-0.3-8.4-0.7-12.5-1-10.5-3.9-42.6-30.3-61.9-20.1-14.7-48.1-18.2-81.2-10.2 4-1.4 7.9-2.9 11.6-4.5 9.7-4.2 39.3-16.9 49.5-47.9 7.8-23.7 2.5-51.4-15.4-80.3 2.6 3.4 5.2 6.6 7.9 9.7 7 7.9 28.2 32.1 60.9 32.3h0.3c24.8 0 49.4-13.6 71.4-39.5-2.4 3.5-4.7 7-6.7 10.5-5.4 9.1-21.8 36.7-11.9 67.9 7.6 23.7 28.2 43 59.7 55.9-4.1-1.3-8.1-2.4-12.1-3.3zM858 462.9c-13.2 16.1-30 30.4-47.4 40.2-50.5 28.6-119.6 27.6-159.1 12.1-17.7-6.9-23.6-14.3-24.2-16.3 0 0-0.7-3.7 5.8-14.8 7.5-12.6 20.7-28.2 34.6-44.8 13.3-15.8 48.7-57.8 107.7-71.6 15.9-3.7 31.3-5.4 42-5.4h0.4c-0.9 1.7-1.8 3.4-2.6 4.8-4.3 8-8.8 16.3-11.7 25.3-6.8 21-1.1 35.7 4.9 44.4 6.1 8.9 18.2 19.7 41.1 20.6 4.4 0.2 8.8 0 13.1-0.4-1.4 1.9-2.9 3.9-4.6 5.9z" p-id="2232"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@ -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="1669164926573" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2820" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M762.38 19.59L430.31 351.68l65.82 65.82 266.25-266.28 127.5 127.5-266.27 266.25 65.82 65.82 332.09-332.07zM292.74 875.86l-127.47-127.5 266.25-266.25-65.82-65.82L33.63 748.36l259.11 259.14 332.07-332.09-65.82-65.82z" p-id="2821"></path><path d="M368.925 606.364L620.39 354.898l65.817 65.817-251.466 251.466z" p-id="2822"></path></svg>

After

Width:  |  Height:  |  Size: 666 B

@ -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="1669617494478" class="icon" viewBox="0 0 1068 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2280" xmlns:xlink="http://www.w3.org/1999/xlink" width="208.59375" height="200"><path d="M-15.042048 759.563264" p-id="2281"></path><path d="M818.241024 375.863296c0-4.145152 1.386496-8.756224 1.837056-12.9024 1.386496-3.224576 1.463296-7.801856 2.768896-11.9808 9.750528-31.286272 39.614464-53.429248 74.616832-53.429248 42.84416 0 78.313472 35.470336 78.313472 78.312448 0 42.835968-35.469312 78.299136-78.313472 78.299136C854.171136 454.163456 818.241024 418.699264 818.241024 375.863296z" p-id="2282"></path><path d="M148.023808 773.42208c0 17.882112 21.650432 30.362624 46.058496 30.362624l476.751872 0c23.959552 0 71.866368-12.480512 71.866368-30.362624l0-31.842304c0-17.000448-47.905792-22.503424-71.866368-22.503424L194.082304 719.076352c-24.408064 0-46.058496 4.518912-46.058496 22.503424L148.023808 773.42208z" p-id="2283"></path><path d="M29.179392 260.701184c0 222.942208 181.029888 405.815296 403.97312 405.815296 146.942976 0 274.9952-85.673984 345.473024-206.35648 27.635712 37.302272 69.097472 60.33408 118.838272 60.33408 79.235072 0 143.7184-64.944128 143.7184-144.169984 0-79.233024-64.483328-144.1792-143.7184-144.1792-21.648384 0-42.37312 14.74048-60.797952 23.487488 0-13.357056-1.84832-4.140032-3.224576-45.597696L32.402944 210.034688C31.027712 251.949056 29.179392 244.122624 29.179392 260.701184z" p-id="2284"></path><path d="M1079.420416 759.563264" p-id="2285"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -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="1669358819632" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2665" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 1024C229.222 1024 0 794.778 0 512S229.222 0 512 0s512 229.222 512 512-229.222 512-512 512z m259.149-568.883h-290.74a25.293 25.293 0 0 0-25.292 25.293l-0.026 63.206c0 13.952 11.315 25.293 25.267 25.293h177.024c13.978 0 25.293 11.315 25.293 25.267v12.646a75.853 75.853 0 0 1-75.853 75.853h-240.23a25.293 25.293 0 0 1-25.267-25.293V417.203a75.853 75.853 0 0 1 75.827-75.853h353.946a25.293 25.293 0 0 0 25.267-25.292l0.077-63.207a25.293 25.293 0 0 0-25.268-25.293H417.152a189.62 189.62 0 0 0-189.62 189.645V771.15c0 13.977 11.316 25.293 25.294 25.293h372.94a170.65 170.65 0 0 0 170.65-170.65V480.384a25.293 25.293 0 0 0-25.293-25.267z" fill="#C71D23" p-id="2666"></path></svg>

After

Width:  |  Height:  |  Size: 1010 B

@ -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="1669358814365" class="icon" viewBox="0 0 1049 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2510" xmlns:xlink="http://www.w3.org/1999/xlink" width="204.8828125" height="200"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" fill="#191717" p-id="2511"></path><path d="M199.040177 753.571326c-0.869171 2.607513-5.215026 3.476684-8.691711 1.738342s-6.084198-5.215026-4.345855-7.82254c0.869171-2.607513 5.215026-3.476684 8.691711-1.738342s5.215026 5.215026 4.345855 7.82254z m-6.953369-4.345856M219.900283 777.038945c-2.607513 2.607513-7.82254 0.869171-10.430053-2.607514-3.476684-3.476684-4.345855-8.691711-1.738342-11.299224 2.607513-2.607513 6.953369-0.869171 10.430053 2.607514 3.476684 4.345855 4.345855 9.560882 1.738342 11.299224z m-5.215026-5.215027M240.760389 807.459932c-3.476684 2.607513-8.691711 0-11.299224-4.345855-3.476684-4.345855-3.476684-10.430053 0-12.168395 3.476684-2.607513 8.691711 0 11.299224 4.345855 3.476684 4.345855 3.476684 9.560882 0 12.168395z m0 0M269.443034 837.011749c-2.607513 3.476684-8.691711 2.607513-13.906737-1.738342-4.345855-4.345855-6.084198-10.430053-2.607513-13.037566 2.607513-3.476684 8.691711-2.607513 13.906737 1.738342 4.345855 3.476684 5.215026 9.560882 2.607513 13.037566z m0 0M308.555733 853.526c-0.869171 4.345855-6.953369 6.084198-13.037566 4.345855-6.084198-1.738342-9.560882-6.953369-8.691711-10.430053 0.869171-4.345855 6.953369-6.084198 13.037566-4.345855 6.084198 1.738342 9.560882 6.084198 8.691711 10.430053z m0 0M351.145116 857.002684c0 4.345855-5.215026 7.82254-11.299224 7.82254-6.084198 0-11.299224-3.476684-11.299224-7.82254s5.215026-7.82254 11.299224-7.82254c6.084198 0 11.299224 3.476684 11.299224 7.82254z m0 0M391.126986 850.049315c0.869171 4.345855-3.476684 8.691711-9.560882 9.560882-6.084198 0.869171-11.299224-1.738342-12.168395-6.084197-0.869171-4.345855 3.476684-8.691711 9.560881-9.560882 6.084198-0.869171 11.299224 1.738342 12.168396 6.084197z m0 0" fill="#191717" p-id="2512"></path></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@ -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="1669544223833" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M940.513333 512a486.42 486.42 0 0 1-27.126666 42.3c-30.993333 43.56-75.62 93.766667-136.44 153.48-63.013333 61.866667-145.153333 135.733333-251.133334 225.806667a21.333333 21.333333 0 0 1-27.626666 0c-106-90.073333-188.12-163.94-251.133334-225.806667-60.82-59.713333-105.446667-109.92-136.44-153.48A486.42 486.42 0 0 1 83.486667 512H234.666667a21.333333 21.333333 0 0 0 15.086666-6.246667l64.4-64.42 114.766667 229.526667A21.333333 21.333333 0 0 0 448 682.666667h1.126667a21.333333 21.333333 0 0 0 18.873333-13.84L578.8 373.333333l106.12 212.24a21.333333 21.333333 0 0 0 34.166667 5.546667L798.166667 512zM62.98 469.333333h162.853333l79.08-79.086666a21.333333 21.333333 0 0 1 34.166667 5.546666L445.2 608.033333 556 312.506667a21.333333 21.333333 0 0 1 39.053333-2.046667L709.846667 540l64.4-64.406667A21.333333 21.333333 0 0 1 789.333333 469.333333h171.686667a281.12 281.12 0 0 0 9.56-28.733333c8.926667-32.666667 10.753333-63.333333 10.753333-99.293333a256 256 0 0 0-469.333333-141.546667A256 256 0 0 0 42.666667 341.333333c0 35.96 1.826667 66.606667 10.753333 99.293334A281.12 281.12 0 0 0 62.98 469.333333z" fill="#5C5C66" p-id="2903"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -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="1674362361779" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25798" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M220.72888889 366.36444445L75.09333333 512l145.63555556 145.63555555v-109.22666666h218.45333333v-72.81777778H220.72888889z m728.17777778 145.63555555L803.27111111 366.36444445v109.22666666H584.81777778v72.81777778h218.45333333v109.22666666z" p-id="25799"></path></svg>

After

Width:  |  Height:  |  Size: 602 B

@ -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="1669795213657" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6261" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M533.333333 85.333333C384 85.333333 251.733333 166.4 183.466667 290.133333L85.333333 192V469.333333h277.333334L243.2 349.866667C298.666667 243.2 405.333333 170.666667 533.333333 170.666667c174.933333 0 320 145.066667 320 320S708.266667 810.666667 533.333333 810.666667c-140.8 0-256-89.6-302.933333-213.333334H140.8c46.933333 170.666667 204.8 298.666667 392.533333 298.666667 226.133333 0 405.333333-183.466667 405.333334-405.333333S755.2 85.333333 533.333333 85.333333zM469.333333 298.666667v217.6l200.533334 119.466666 34.133333-55.466666-170.666667-102.4V298.666667H469.333333z" p-id="6262"></path></svg>

After

Width:  |  Height:  |  Size: 939 B

@ -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="1669126954083" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2723" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M946.5 505L534.6 93.4c-12.5-12.5-32.7-12.5-45.2 0L77.5 505c-12 12-18.8 28.3-18.8 45.3 0 35.3 28.7 64 64 64h43.4V908c0 17.7 14.3 32 32 32H448V716h112v224h265.9c17.7 0 32-14.3 32-32V614.3h43.4c17 0 33.3-6.7 45.3-18.8 24.9-25 24.9-65.5-0.1-90.5z" p-id="2724"></path></svg>

After

Width:  |  Height:  |  Size: 602 B

@ -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="1669537925642" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2227" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M872.802928 755.99406 872.864326 755.99406 872.864326 755.624646Z" p-id="2228"></path><path d="M744.055658 192.799074c-4.814656-2.889817-9.601682-5.251607-15.442714-5.251607-14.262842 0-25.758664 11.559267-25.758664 25.805736 0 10.285251 6.088672 18.519796 14.6957 23.195282 94.679359 55.247278 158.344355 157.787676 158.344355 275.30416 0 117.424386-63.605643 219.931015-158.159136 275.18034-8.29492 4.538363-15.442714 13.050224-15.442714 23.583115 0 14.261818 11.559267 25.820062 25.791409 25.820062 5.716188 0 10.252505-2.202155 15.22475-5.063319 109.871363-64.133669 183.764304-183.143157 183.764304-319.520197C927.074995 375.785665 853.495186 257.010515 744.055658 192.799074z" p-id="2229"></path><path d="M773.946432 511.867994c0-79.96524-43.344181-149.739373-107.821681-187.289594-2.920516-1.52268-9.785877-4.520967-14.603603-4.520967-14.325263 0-25.914206 11.589966-25.914206 25.89988 0 9.616008 5.096065 18.176988 12.865006 22.666232 49.839105 28.307719 83.45983 81.829703 83.45983 143.244448 0 62.472843-34.801621 116.817566-86.070284 144.750755-7.457856 4.538363-12.397355 12.803607-12.397355 22.188348 0 14.325263 11.588943 25.943882 25.882484 25.943882 6.090718 0.031722 13.33061-3.542686 13.33061-3.542686C729.048873 664.171772 773.946432 593.294514 773.946432 511.867994z" p-id="2230"></path><path d="M541.3694 124.672464c-10.846022-5.219885-23.740704-3.790326-33.215496 3.712555-0.435928 0.358157-46.423309 36.914748-97.195669 74.296123-88.308255 65.081251-114.036219 75.925227-119.257128 77.649498l-110.6194 0c-0.63752 0-1.243317 0.062422-1.879813 0.093121l-56.504922 0c-14.231119 0-25.775037 11.543917-25.775037 25.775037l0 411.697573c0 14.261818 11.512195 25.761734 25.775037 25.761734l189.511191 0.027629c5.096065 1.865487 29.395494 13.0799 107.761306 76.999698 45.613874 37.162388 86.505189 73.485665 86.940095 73.829496 5.841032 5.218862 13.298887 7.92039 20.820188 7.92039 4.349051 0 8.729825-0.930185 12.862959-2.764973 11.277858-5.064342 18.517749-16.252149 18.517749-28.619828 0 0 0.031722-97.257068 0.031722-132.212184 0.808412-2.484587 1.213641-5.127787 1.213641-7.863085 0-2.792603-1.245364-578.026786-1.245364-578.026786C559.110459 140.892891 552.214399 129.924071 541.3694 124.672464zM508.308423 726.470653c0 1.494027-0.467651 94.617961-0.467651 94.617961-13.889335-11.745509-29.332049-24.64019-45.240367-37.507242-104.59008-84.702124-130.505309-91.816149-148.030451-91.816149-0.372483 0-0.683569 0.091074-1.025353 0.091074s-0.652869-0.091074-1.025353-0.091074L170.394297 691.765223c-18.037818 0-22.248723-5.128811-22.248723-23.246447L148.145573 352.559685c0-12.32163 1.461281-20.057825 16.298198-20.057825l128.065747 0c17.090237 0 43.315528-6.991228 157.787676-90.839915 20.383236-14.914688 40.330544-29.938869 57.544601-43.113937 0 0 0.373507 445.207781 0.467651 521.368368C507.779374 722.028481 508.308423 724.234729 508.308423 726.470653z" p-id="2231"></path></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -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="1669686702410" class="icon" viewBox="0 0 1071 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2231" xmlns:xlink="http://www.w3.org/1999/xlink" width="209.1796875" height="200"><path d="M1041.441824 418.173769C1017.545784 379.457987 976.978907 357.655147 934.856203 355.990951 932.672662 355.651924 930.455865 355.426732 928.182457 355.426732L681.491077 355.156994C698.221007 307.082112 707.361417 255.423948 707.361417 201.600472 707.361417 166.693164 703.416492 132.726219 696.177769 100.007732L695.526642 100.09187C682.3613 42.777911 631.382524 0 570.359886 0 499.341382 0 441.78117 57.86828 441.78117 129.246872 441.78117 133.195164 442.028573 137.076641 442.364598 140.942034 438.548914 278.142407 331.614976 389.360269 196.661604 399.069528L196.661604 399.904721 49.99039 400.248696C48.21671 400.029691 46.431955 399.882449 44.609042 399.882449 20.192356 399.882449 0.39757 419.774863 0.39757 444.313419L0 977.678089C0 1002.211696 19.782477 1022.104111 44.199165 1022.104111 46.59566 1022.104111 48.930613 1021.861596 51.223717 1021.494111L214.393457 1021.562164C216.553627 1021.888817 218.732259 1022.104111 220.969974 1022.104111 223.210149 1022.104111 225.381396 1021.888817 227.525566 1021.56835L840.966989 1021.82695 840.966989 1022.092974C864.997185 1022.137518 889.32402 1015.639107 911.109115 1001.722954 931.788904 988.498463 947.345814 970.345723 957.569383 949.811138 960.374515 945.715604 962.586401 941.106583 963.928028 936.029854L1059.429687 512.279478C1060.754092 507.254717 1061.113516 502.206443 1060.720858 497.29428 1062.705021 470.461729 1056.644245 442.797699 1041.441824 418.173769L1041.441824 418.173769ZM265.44116 938.490887 177.048986 938.469853 177.38132 494.580834C177.38132 494.580834 231.384331 494.238097 265.862117 483.495673L265.44116 938.490887 265.44116 938.490887Z" p-id="2232"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -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="1675830054626" class="icon" viewBox="0 0 1042 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2221" xmlns:xlink="http://www.w3.org/1999/xlink" width="203.515625" height="200"><path d="M581.632 697.344l126.976 0 0 194.56q0 33.792-10.24 58.88t-27.136 40.96-39.424 23.552-48.128 7.68l-452.608 0q-24.576 0-48.128-9.728t-41.472-27.136-29.184-40.96-11.264-52.224l0-706.56q0-24.576 11.776-47.104t30.208-39.936 40.96-28.16 45.056-10.752l449.536 0q26.624 0 50.176 11.776t41.472 29.696 28.16 40.448 10.24 44.032l0 188.416-126.976 0 1.024-195.584-452.608 0-1.024 713.728 452.608 0 0-195.584zM1021.952 505.856q37.888 30.72 2.048 60.416-20.48 15.36-44.544 37.888t-50.176 46.592-51.712 47.616-47.104 40.96q-23.552 18.432-40.448 18.432t-16.896-24.576q2.048-14.336 0.512-35.84t-1.536-36.864q0-17.408-12.288-21.504t-29.696-4.096l-40.96 0-62.464 0q-34.816 0-73.216-0.512t-73.216-0.512l-62.464 0-41.984 0q-8.192 0-17.92-1.536t-17.408-6.656-12.288-14.336-4.608-23.552q0-19.456-0.512-46.08t0.512-47.104q0-27.648 13.312-37.888t43.008-9.216l33.792 0 59.392 0q32.768 0 70.144 0.512t71.168 0.512l61.44 0 38.912 0q25.6 1.024 43.52-4.096t17.92-22.528q0-14.336 1.024-32.256t1.024-32.256q0-23.552 12.8-29.696t32.256 9.216q19.456 16.384 45.568 38.4t52.736 45.056 52.736 45.568 47.616 39.936z" p-id="2222"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -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="1669170449235" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2558" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M510.563278 65.99404c-246.704798 0-446.604594 199.925379-446.604594 446.579011 0 246.648516 199.899796 446.573895 446.63427 446.573895 246.619864 0 446.574918-199.925379 446.574918-446.573895C957.166849 265.918395 757.212818 65.99404 510.563278 65.99404zM260.657578 583.67032c-39.266305 0-71.098291-31.830963-71.100338-71.097268l0 0 0-0.001023c0 0 0-0.001023 0-0.001023 0-39.267329 31.833009-71.100338 71.100338-71.100338 39.267329 0 71.100338 31.833009 71.100338 71.100338S299.924907 583.67032 260.657578 583.67032zM511.420809 583.67032c-39.267329 0-71.100338-31.833009-71.100338-71.100338s31.833009-71.100338 71.100338-71.100338c39.267329 0 71.100338 31.833009 71.100338 71.100338S550.688137 583.67032 511.420809 583.67032zM765.455549 583.67032c-39.267329 0-71.100338-31.833009-71.100338-71.100338s31.833009-71.100338 71.100338-71.100338c39.267329 0 71.100338 31.833009 71.100338 71.100338S804.722878 583.67032 765.455549 583.67032z" p-id="2559"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -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="1674274584544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12364" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M419.072 95.488a384 384 0 0 0 509.44 509.44C886.101333 795.904 715.733333 938.666667 512 938.666667 276.352 938.666667 85.333333 747.648 85.333333 512c0-203.733333 142.762667-374.101333 333.738667-416.512z m355.925333 2.261333L810.666667 106.666667v42.666666l-35.669334 8.917334a85.333333 85.333333 0 0 0-62.08 62.08L704 256h-42.666667l-8.917333-35.669333a85.333333 85.333333 0 0 0-62.08-62.08L554.666667 149.333333v-42.666666l35.669333-8.917334A85.333333 85.333333 0 0 0 652.373333 35.669333L661.333333 0h42.666667l8.917333 35.669333a85.333333 85.333333 0 0 0 62.08 62.08z m213.333334 213.333334L1024 320v42.666667l-35.669333 8.917333a85.333333 85.333333 0 0 0-62.08 62.08L917.333333 469.333333h-42.666666l-8.917334-35.669333a85.333333 85.333333 0 0 0-62.08-62.08L768 362.666667v-42.666667l35.669333-8.917333a85.333333 85.333333 0 0 0 62.08-62.08L874.666667 213.333333h42.666666l8.917334 35.669334a85.333333 85.333333 0 0 0 62.08 62.08z" p-id="12365"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -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="1669170511541" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2712" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M565.747623 792.837176l260.819261 112.921839 126.910435-845.424882L66.087673 581.973678l232.843092 109.933785 562.612725-511.653099-451.697589 563.616588-5.996574 239.832274L565.747623 792.837176z" p-id="2713"></path></svg>

After

Width:  |  Height:  |  Size: 556 B

@ -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="1675326072524" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4800" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M633.3 155.8s39.4-181.4-378.1-13.1V582S668.3 372.2 618 595.2c0 0 244.7-76.6 292.8-65.5V96.8c0.1 0-209.7 24-277.5 59zM166.7 64c-29.6 0-53.5 23.9-53.5 53.5v789c0 29.6 23.9 53.5 53.5 53.5s53.6-23.9 53.6-53.5v-789c0-29.6-24-53.5-53.6-53.5z" p-id="4801"></path></svg>

After

Width:  |  Height:  |  Size: 595 B

@ -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="1680783788790" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2221" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 0C229.224296 0 0 229.224296 0 512s229.224296 512 512 512 512-229.224296 512-512S794.775704 0 512 0zM801.261037 668.86163c-21.731556 18.640593-49.948444-61.345185-54.006519-49.038222-9.879704 29.923556-14.506667 49.929481-43.633778 82.507852-1.554963 1.744593 33.659259 14.468741 43.633778 41.642667 9.557333 26.017185 28.141037 67.26163-93.487407 80.213333-71.35763 7.585185-122.936889-38.020741-128.075852-37.584593-9.53837 0.83437-5.290667 0-15.530667 0-8.38163 0-8.931556 0.606815-16.820148 0-2.161778-0.170667-25.884444 37.584593-131.963259 37.584593-82.223407 0-103.518815-51.749926-86.983111-80.213333 16.535704-28.463407 44.126815-36.750222 40.239407-41.263407-19.152593-22.186667-32.350815-45.909333-40.239407-67.356444-1.953185-5.347556-3.584-10.543407-4.873481-15.530667-2.996148-11.45363-25.884444 67.204741-50.460444 49.038222-24.576-18.166519-22.376296-64.417185-6.46637-108.676741 16.042667-44.619852 56.471704-87.589926 56.926815-97.071407 1.611852-35.290074-3.489185-41.14963 0-50.422519 7.755852-20.764444 17.199407-12.8 17.199407-23.570963 0-135.736889 100.864-245.76 225.28-245.76s225.28 110.042074 225.28 245.76c0 5.195852 13.520593 0 19.986963 23.570963 1.327407 4.873481 2.23763 23.665778 0.663704 50.422519-0.739556 12.856889 34.266074 28.501333 52.375704 97.071407C828.434963 628.754963 810.30637 661.105778 801.261037 668.86163z" fill="#1296db" p-id="2222"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -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="1675161410837" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2221" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M426.666667 0H42.666667A42.666667 42.666667 0 0 0 0 42.666667V426.666667a42.666667 42.666667 0 0 0 42.666667 42.666666H426.666667a42.666667 42.666667 0 0 0 42.666666-42.666666V42.666667A42.666667 42.666667 0 0 0 426.666667 0z m-42.666667 384H85.333333V85.333333h298.666667v298.666667z m42.666667 170.666667H42.666667A42.666667 42.666667 0 0 0 0 597.333333v384A42.666667 42.666667 0 0 0 42.666667 1024H426.666667a42.666667 42.666667 0 0 0 42.666666-42.666667V597.333333a42.666667 42.666667 0 0 0-42.666666-42.666666zM384 938.666667H85.333333V640h298.666667V938.666667z m597.333333-938.666667H597.333333a42.666667 42.666667 0 0 0-42.666666 42.666667V426.666667a42.666667 42.666667 0 0 0 42.666666 42.666666h384A42.666667 42.666667 0 0 0 1024 426.666667V42.666667A42.666667 42.666667 0 0 0 981.333333 0zM938.666667 384H640V85.333333H938.666667v298.666667zM170.666667 170.666667h128v128H170.666667V170.666667z m0 554.666666h128V853.333333H170.666667v-128z m725.333333-170.666666H1024V682.666667h-128v-128z m0 341.333333h-85.333333V1024H1024v-213.333333h-128v85.333333z m-341.333333 0H682.666667V1024h-128v-128z m170.666666-725.333333H853.333333v128h-128V170.666667z m-170.666666 384H682.666667V682.666667h-128v-128zM682.666667 682.666667h128v213.333333H682.666667V682.666667z" p-id="2222"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -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="1669472705351" class="icon" viewBox="0 0 1035 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2148" xmlns:xlink="http://www.w3.org/1999/xlink" width="202.1484375" height="200"><path d="M530.850448 573.163313c32.005172-31.883636 32.111192-87.434343-0.069818-119.489939C399.437114 322.845737 268.507336 191.603071 137.436629 60.506505c-12.621576-12.625455-27.585939-20.686869-45.26804-23.540364-3.529697-0.570182-7.085253-0.999434-10.630465-1.499798-1.025293 0-2.055758 0-3.081051 0-4.035232 0.575354-8.111838 0.943838-12.091475 1.757091-33.298101 6.818909-54.838303 26.616242-63.959919 59.278222-3.201293 11.479919-2.806949 24.85398-1.135192 35.701657 1.751919 11.344162 7.11499 21.818182 14.479515 30.904889 3.444364 4.252444 7.050343 8.418263 10.918788 12.291879 111.045818 111.127273 222.142061 222.222222 333.247354 333.293899 1.444202 1.444202 3.227152 2.554828 5.187232 4.080485-2.121697 2.222545-3.475394 3.696485-4.879515 5.100606C252.653437 625.450667 145.164468 733.112889 37.416912 840.506182c-15.829333 15.773737-33.541172 31.162182-36.146424 54.273293-1.233455 10.908444-1.859232 22.111677 0 32.929616 0.919273 5.363071 3.262061 10.423596 5.494949 15.358707 23.655434 52.318384 89.514667 64.241778 130.66602 23.186101C268.668953 835.315071 399.501761 703.987071 530.850448 573.163313L530.850448 573.163313zM78.451902 35.466343l-12.091475 1.757091C70.345235 36.410182 74.421841 36.041697 78.451902 35.466343L78.451902 35.466343zM551.467498 36.441212c-38.000485 2.858667-70.434909 37.034667-71.651556 75.106263-0.79903 24.979394 8.131232 45.650747 25.691798 63.197091 111.383273 111.252687 222.661818 222.615273 334.015354 333.893818 1.534707 1.534707 3.686141 2.448808 6.595232 4.327434-3.35903 2.667313-5.116121 3.803798-6.565495 5.253172-68.050747 68.000323-136.075636 136.035556-204.100525 204.065616C591.916791 765.814949 548.391619 809.360808 504.845761 852.880808c-19.449535 19.439192-28.328081 42.706747-24.045899 70.054788 4.829091 30.919111 22.440081 52.516202 51.712 63.010909 29.450343 10.550303 56.692364 4.803232 80.49002-15.848727 1.944566-1.682101 3.798626-3.470222 5.616485-5.288081 130.121697-130.111354 259.955071-260.509737 390.546101-390.141414 33.272242-33.035636 33.454545-88.934141 1.206303-121.050505C879.016912 322.804364 748.093599 191.557818 617.028064 60.456081c-12.626747-12.626747-27.611798-20.655838-45.288727-23.505455-3.534869-0.570182-7.090424-0.994263-10.635636-1.484283-1.030465 0-2.055758 0-3.086222 0.005172C555.835013 35.799919 553.659013 36.274424 551.467498 36.441212L551.467498 36.441212zM551.467498 36.441212" p-id="2149"></path></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -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="1669794880781" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6319" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M789.804097 737.772047 742.865042 784.699846 898.765741 940.600545 945.704796 893.672746Z" p-id="6320"></path><path d="M456.92259 82.893942c-209.311143 0-379.582131 170.282245-379.582131 379.582131s170.270988 379.570875 379.582131 379.570875c209.287607 0 379.558595-170.270988 379.558595-379.570875S666.210197 82.893942 456.92259 82.893942zM770.128989 462.477097c0 172.721807-140.508127 313.229934-313.206398 313.229934-172.720783 0-313.229934-140.508127-313.229934-313.229934s140.508127-313.229934 313.229934-313.229934C629.620861 149.247162 770.128989 289.75529 770.128989 462.477097z" p-id="6321"></path></svg>

After

Width:  |  Height:  |  Size: 946 B

@ -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="1669186304076" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2201" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 512m-299.52 0a299.52 299.52 0 1 0 599.04 0 299.52 299.52 0 1 0-599.04 0Z" p-id="2202"></path><path d="M486.4 0h48.64v125.44H486.4zM234.8544 78.9504l42.112-24.32 62.72 108.6464-42.112 24.32zM58.0608 275.8144l24.32-42.1376 108.6464 62.72-24.32 42.1376zM0 486.4h125.44v48.64H0zM55.8592 746.7264l108.6464-62.72 24.32 42.1376-108.6464 62.72zM235.6736 940.416l62.72-108.6208 42.1376 24.32-62.72 108.6208zM486.4 896h48.64v125.44H486.4zM683.8528 857.0112l42.1376-24.32 62.72 108.6208-42.1376 24.32zM833.8688 724.3776l24.32-42.1376 108.6208 62.7456-24.32 42.1376zM896 486.4h125.44v48.64H896zM833.8944 297.6512l108.6464-62.72 24.32 42.1376-108.672 62.72zM684.288 164.608l62.72-108.6208 42.112 24.32-62.72 108.6464z" p-id="2203"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -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="1669164870986" class="icon" viewBox="0 0 1097 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2666" xmlns:xlink="http://www.w3.org/1999/xlink" width="214.2578125" height="200"><path d="M256 256q0-30.285714-21.428571-51.714286T182.857143 182.857143t-51.714286 21.428571T109.714286 256t21.428571 51.714286T182.857143 329.142857t51.714286-21.428571T256 256z m609.714286 329.142857q0 30.285714-21.142857 51.428572l-280.571429 281.142857q-22.285714 21.142857-52 21.142857-30.285714 0-51.428571-21.142857L52 508.571429q-21.714286-21.142857-36.857143-57.714286T0 384V146.285714q0-29.714286 21.714286-51.428571t51.428571-21.714286h237.714286q30.285714 0 66.857143 15.142857T436 125.142857l408.571429 408q21.142857 22.285714 21.142857 52z m219.428571 0q0 30.285714-21.142857 51.428572l-280.571429 281.142857q-22.285714 21.142857-52 21.142857-20.571429 0-33.714285-8t-30.285715-25.714286l268.571429-268.571428q21.142857-21.142857 21.142857-51.428572 0-29.714286-21.142857-52L527.428571 125.142857q-21.714286-21.714286-58.285714-36.857143T402.285714 73.142857h128q30.285714 0 66.857143 15.142857t58.285714 36.857143l408.571429 408q21.142857 22.285714 21.142857 52z" p-id="2667"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -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="1669170420386" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2404" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 85.333333c235.637333 0 426.666667 191.029333 426.666667 426.666667S747.637333 938.666667 512 938.666667a424.778667 424.778667 0 0 1-219.125333-60.501334 2786.56 2786.56 0 0 0-20.053334-11.765333l-104.405333 28.48c-23.893333 6.506667-45.802667-15.413333-39.285333-39.296l28.437333-104.288c-11.008-18.688-18.218667-31.221333-21.802667-37.909333A424.885333 424.885333 0 0 1 85.333333 512C85.333333 276.362667 276.362667 85.333333 512 85.333333z m-102.218667 549.76a32 32 0 1 0-40.917333 49.216A223.178667 223.178667 0 0 0 512 736c52.970667 0 103.189333-18.485333 143.104-51.669333a32 32 0 1 0-40.906667-49.216A159.189333 159.189333 0 0 1 512 672a159.189333 159.189333 0 0 1-102.218667-36.906667z" p-id="2405"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -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="1672798822487" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2239" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M951.296 424.96L1024 352.256 671.744 0 599.04 72.704l70.144 70.656-168.96 168.96a296.96 296.96 0 0 0-286.72 75.264L143.36 458.24 72.704 387.584 0 460.8l245.248 245.248-139.776 139.776 72.704 72.704 140.288-140.288L563.2 1024l72.704-72.704-70.144-70.656 70.144-70.144a296.96 296.96 0 0 0 75.776-287.232l168.96-168.96z" p-id="2240"></path></svg>

After

Width:  |  Height:  |  Size: 676 B

@ -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="1669360364430" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2231" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M262.826667 605.866667l1.962666 0.725333 186.026667 57.216 58.026667 193.109333A63.488 63.488 0 0 1 448 938.666667a114.688 114.688 0 0 1-109.866667-81.749334L262.869333 605.866667zM874.666667 85.333333a42.666667 42.666667 0 0 1 42.666666 42.666667v640a42.666667 42.666667 0 0 1-85.333333 0V128a42.666667 42.666667 0 0 1 42.666667-42.666667z m-85.333334 85.333334v554.666666l-554.666666-170.666666V341.333333l554.666666-170.666666z m-597.333333 170.666666v213.333334h-42.666667a42.666667 42.666667 0 0 1-42.666666-42.666667V384a42.666667 42.666667 0 0 1 42.666666-42.666667h42.666667z" p-id="2232"></path></svg>

After

Width:  |  Height:  |  Size: 943 B

@ -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="1669456204739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6101" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M449.1264 1000.0384 449.1264 218.624 80.7936 583.8848 0 512l512-512 512 512L937.1648 583.8848 574.8736 218.624l0 781.5168L449.1264 1000.1408z" p-id="6102"></path></svg>

After

Width:  |  Height:  |  Size: 501 B

@ -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="1674612454996" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="46508" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M824.264 95.36c0-23.859 25.043-44.16 48.902-44.16s49.714 20.301 49.714 44.16v190.08c0 23.859-19.054 52.868-42.913 52.868h-190.08c-23.859 0-46.696-25.96-46.696-49.819s22.55-46.249 46.409-46.249h82.025C702.344 175.534 610.22 155.853 512 155.853c-206.775 0-360.398 149.372-360.398 356.147 0 206.775 153.623 358.23 360.398 358.23 206.775 0 357.467-151.455 357.467-358.23 0-23.859 23.634-50.706 53.413-50.706 29.78 0 49.92 26.847 49.92 50.706 0 254.493-206.307 460.8-460.8 460.8-254.493 0-460.8-206.307-460.8-460.8C51.2 257.507 257.507 51.2 512 51.2c122.4 0 226.684 33.296 312.264 117.369 0.358 0.351 0.358-24.052 0-73.209z" p-id="46509"></path></svg>

After

Width:  |  Height:  |  Size: 980 B

@ -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="1674182987349" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2245" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M298.666667 298.666667a213.333333 213.333333 0 1 0 213.333333-213.333334 213.333333 213.333333 0 0 0-213.333333 213.333334zM128 831.573333z m0 0z m0 0z m768 2.56z m0 0z m-768 0z m578.56-275.2h-17.493333a50.346667 50.346667 0 0 0-20.906667 5.12s-14.08 8.106667-26.88 13.653334a331.946667 331.946667 0 0 1-128 25.6 321.706667 321.706667 0 0 1-128-25.6c-12.8-5.546667-27.306667-13.653333-27.306667-13.653334a42.666667 42.666667 0 0 0-20.906666-5.12h-18.346667a219.306667 219.306667 0 0 0-165.12 136.533334 362.666667 362.666667 0 0 0-25.6 134.4 42.666667 42.666667 0 0 0 21.333333 32.426666S268.8 938.666667 512 938.666667s362.666667-76.373333 362.666667-76.373334a42.666667 42.666667 0 0 0 21.333333-32.853333 346.88 346.88 0 0 0-24.746667-132.266667 218.88 218.88 0 0 0-164.693333-139.946666zM896 829.866667z m0 0z" p-id="2246"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -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="1669365040360" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2231" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M126.2 898.2V64H64V960h896v-61.8z" fill="#7D7B81" p-id="2232"></path><path d="M897 192L576 513 381 384 192 640v192h705z" fill="#7D7B81" p-id="2233"></path></svg>

After

Width:  |  Height:  |  Size: 494 B

@ -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="1669626306018" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2288" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 288c-124.8 0-224 99.2-224 224s99.2 224 224 224 224-99.2 224-224S636.8 288 512 288zM512 688c-96 0-176-80-176-176s80-176 176-176 176 80 176 176S608 688 512 688z" p-id="2289"></path><path d="M768 371.2a1.6 1.6 0 1 0 102.4 0 1.6 1.6 0 1 0-102.4 0Z" p-id="2290"></path><path d="M864 224l-96 0-22.4-67.2c-6.4-16-25.6-28.8-41.6-28.8l-384 0c-19.2 0-35.2 12.8-41.6 28.8l-22.4 67.2-96 0c-54.4 0-96 41.6-96 96l0 448c0 54.4 44.8 96 96 96l704 0c54.4 0 96-41.6 96-96l0-448C960 265.6 918.4 224 864 224zM912 768c0 25.6-22.4 48-48 48l-704 0c-25.6 0-48-22.4-48-48l0-448c0-25.6 22.4-48 48-48l96 0 35.2 0 9.6-32 22.4-64 377.6 0 22.4 64 9.6 32 35.2 0 96 0c25.6 0 48 22.4 48 48L912 768z" p-id="2291"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -0,0 +1,10 @@
export default {
// gitee的client-id
GITEE_APP_ID: "***************************",
// gitee回调地址
GITEE_REDIRECT_URI: "***************************",
// github的client-id
GITHUB_APP_ID: "***************************",
// github回调地址
GITHUB_REDIRECT_URL: "***************************",
};

@ -0,0 +1,461 @@
@import "./mixin.scss";
/* 背景色 */
.bg {
background-color: var(--grey-0);
}
/* 页面布局 */
.page-header {
position: relative;
width: 100%;
height: 70vh;
background: var(--color-red) no-repeat center center / cover;
z-index: -9;
&::after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .2);
transition: all .2s ease-in-out 0s;
}
}
.page-title {
@include flex;
flex-direction: column;
position: fixed;
width: 100%;
height: 50vh;
min-height: 10rem;
padding: 4rem 5rem 0;
font-size: 2.25em;
color: var(--header-text-color);
animation: titleScale 1s;
z-index: 1;
}
.page-cover {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 70vh;
object-fit: cover;
}
.page-container {
position: relative;
width: calc(100% - 0.625rem);
margin: 1.5rem auto;
padding: 1.75rem 2.25rem;
border-radius: 0.75rem;
box-shadow: 0 0 1rem var(--box-bg-shadow);
animation: slideUpIn 1s;
}
@media (min-width: 1200px) {
.page-container {
width: 60.5rem;
}
}
@media (max-width: 767px) {
.page-container {
padding: 1rem 0.875rem;
}
.page-title {
font-size: 2rem;
padding: 3rem 0.5rem 0;
}
}
.main-container {
display: flex;
align-items: flex-start;
justify-content: center;
width: calc(100% - 0.625rem);
margin: 0 auto;
padding-bottom: 1.75rem;
animation: slideUpIn 1s;
}
.left-container {
width: calc(100% - 18.75rem);
transition: all 0.3s;
}
.right-container {
position: sticky;
top: 1rem;
width: 18rem;
margin-left: 0.8rem;
}
.test {
width: 100%;
}
.temp {
display: none;
}
@media (min-width: 1200px) {
.main-container {
width: 72.5rem;
}
}
@media (max-width: 991px) {
.left-container {
width: 100%;
}
.right-container {
display: none;
width: 100%;
}
}
/* 卡片 */
.side-card {
padding: 1rem;
border-radius: 0.5rem;
box-shadow: 0 0 1rem var(--box-bg-shadow);
transition: all 0.2s ease-in-out 0s;
&:not(:first-child) {
margin-top: 1.25rem;
}
}
@media (max-width: 991px) {
.side-card {
margin: 0 1rem;
}
}
/* 对话框 */
.dialog-wrapper {
width: 600px !important;
}
@media (min-width: 760px) {
.dialog-wrapper {
padding: 2rem 2.5rem 0;
height: 500px;
}
}
.dialog-text {
color: var(--grey-5);
}
.colorFlag {
cursor: pointer;
color: var(--grey-6);
}
/* 边距 */
.mt-4 {
margin-top: 1rem;
}
.mt-12 {
margin-top: 65px;
}
.mt-10 {
margin-top: 40px;
}
.mt-11 {
margin-top: 55px;
}
/* 隐藏抽屉滚动条 */
.n-drawer-body-content-wrapper::-webkit-scrollbar {
display: none !important;
}
/* 代码 */
.hljs {
font-family: "consolas";
font-size: 1rem;
}
/* 分页 */
.n-pagination-item:hover,
.n-pagination-item--active {
color: var(--grey-0) !important;
background-image: linear-gradient(to right, var(--color-pink) 0, var(--color-orange) 100%) !important;
box-shadow: 0 0 .75rem var(--color-pink-a3) !important;
border: none !important;
}
.pagination {
justify-content: center;
padding: 1.25rem 3.125rem;
}
.n-pagination .n-pagination-item {
color: var(--grey-5);
}
/* 加载更多按钮 */
.loading-warp {
@include flex;
margin-top: 20px;
}
.loading-warp .btn {
letter-spacing: 1.25px;
color: var(--grey-0) !important;
background-image: linear-gradient(to right, var(--color-pink) 0, var(--color-orange) 100%);
}
/* 文章标签 */
.article-tag {
display: inline-block;
position: relative;
font-size: 0.75em;
padding: 0 0.3125rem;
border-radius: 0.3125rem;
background: var(--note-bg);
color: var(--note-text);
&:not(:last-child) {
margin-right: 0.625rem;
}
&:hover {
color: #e9546b;
&:before {
width: 104%;
left: -2%;
}
}
&:before {
content: "";
position: absolute;
bottom: 0;
height: 100%;
width: 0;
right: 0;
background: var(--color-red-a1);
border-radius: 0.25rem;
transition: all 0.2s ease-in-out 0s;
}
}
.tag-info {
text-align: left;
margin-top: 0.625rem;
font-size: 0.75em;
}
/* 评论框 */
.reply-box {
display: flex;
flex-direction: column;
}
.box-normal {
display: flex;
height: 50px;
transition: 0.2s;
.reply-box-warp {
flex: auto;
margin-left: 0.6rem;
}
.reply-box-send {
@include flex;
flex-basis: 70px;
margin-left: 10px;
border-radius: 4px;
background-color: var(--comment-btn);
color: var(--grey-0);
cursor: pointer;
}
.send-active {
background-color: var(--color-pink);
}
}
.reply-box-avatar {
@include flex;
width: 3rem;
height: 3.125rem;
}
.reply-box-textarea {
width: 100%;
height: 100%;
padding: 5px 10px;
border: 1px solid var(--grey-3);
border-radius: 6px;
background-color: var(--comment-color);
font-size: 12px;
line-height: 38px;
color: var(--text-color);
resize: none;
outline: none;
}
.box-expand {
display: flex;
align-items: center;
margin-left: 3.6rem;
margin-top: 0.3125rem;
}
.shoka-avatar {
width: 3rem;
height: 3rem;
border-radius: 50%;
}
/* 抽屉 */
.side-bg {
background: var(--grey-1);
}
.author-avatar {
display: block;
max-width: 10rem;
margin: 0 auto;
padding: 0.125rem;
box-shadow: 0 0 1rem 0.625rem var(--body-bg-shadow);
border: 0.0625rem solid var(--body-bg-shadow);
border-radius: 50%;
animation: 1000ms ease-in-out 0ms 1 normal forwards running blur;
&:hover {
-webkit-animation: author-shake 1s;
animation: 1000ms ease 0ms 1 normal none running author-shake;
}
}
.author-name {
margin-top: 0.5rem;
font-weight: 400;
text-align: center;
color: var(--grey-7);
}
.site-desc {
margin-top: 0.5rem;
font-size: 1em;
text-align: center;
color: var(--grey-5);
}
.blog-container {
display: flex;
justify-content: center;
margin-top: 0.8rem;
line-height: 1.4;
text-align: center;
}
.blog-item {
color: var(--grey-6);
padding: 0 0.7rem;
&:not(:first-child) {
border-left: 0.0625rem solid var(--grey-4);
}
}
.count {
font-size: 1.25rem;
font-weight: 600;
text-align: center;
}
.name {
font-size: 0.875rem;
}
.social-container {
margin-top: 1rem;
text-align: center;
.social-item {
display: inline-block;
width: 1.875rem;
height: 1.875rem;
margin: 0 0.125rem;
text-align: center;
}
}
/* 说说 */
.talk-user-name {
display: flex;
align-items: center;
font-size: 0.875rem;
font-weight: 600;
margin-right: 0.3125rem;
color: #ef89c6;
}
.talk-content {
margin-top: 0.3125rem;
font-size: 0.9375rem;
line-height: 1.5rem;
word-wrap: break-word;
word-break: break-all;
white-space: pre-line;
}
.talk-image {
display: flex;
align-items: center;
justify-content: flex-start;
align-content: flex-start;
flex-wrap: wrap;
margin-top: 0.3125rem;
.image {
max-width: 15rem;
max-height: 12.5rem;
padding: 1px;
border-radius: 0.25rem;
cursor: pointer;
object-fit: cover;
}
}
.talk-time,
.talk-like,
.talk-comment {
font-size: 0.8125rem;
margin-right: 1.25rem;
color: #9499a0;
}
/* 点赞 */
.like-flag {
color: var(--color-pink);
}
/* 音乐播放器显示隐藏 */
.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
left: -66px !important;
}
.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
left: 0 !important;
}

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

Loading…
Cancel
Save