Vue2项目练手——通用后台管理项目第八节

news2024/12/28 2:00:09

Vue2项目练手——通用后台管理项目

  • 菜单权限功能
    • tab.js
    • Login.vue
    • CommonAside.vue
    • router/index.js
  • 权限管理问题解决
    • router/tab.js
    • CommonHeader.vue
    • main.js

菜单权限功能

  1. 不同的账号登录,会有不同的菜单权限
  2. 通过url输入地址来显示页面
  3. 对于菜单的数据在不同页面之间的数据通信

tab.js

import Cookie from "js-cookie";
export default {
    state:{
        menu:[]
    },
	mutations:{
	//设置menu的数据
        setMenu(state,val){
            state.menu=val
            console.log("val",val)
            Cookie.set('menu',JSON.stringify(val))
        },
        //动态注册路由
        addMenu(state,router){
            //判断缓存中是否有数据
            if(!Cookie.get('menu')) return
            const menu=JSON.parse(Cookie.get('menu'))
            state.menu=menu
            //组装动态路由的数据
            const menuArray=[]
            menu.forEach(item=>{
                if(item.children){
                    item.children= item.children.map(item=>{
                        item.component=()=>import(`../pages/${item.url}`)
                        return item
                    })
                    menuArray.push(...item.children)
                }else{
                    item.component=()=>import(`../pages/${item.url}`)
                    menuArray.push(item)
                }
            })
            console.log("menuArray",menuArray)
            //路由的动态添加
            menuArray.forEach(item=>{
                router.addRoute('main',item)
            })
            console.log("menuArray",menuArray)
        }
    }

全部代码:

import Cookie from "js-cookie";
export default {
    state:{
        isCollapse:false,  //控制菜单的展开还是收起
        tabsList:[
            {
                path:'/',
                name:"home",
                label:"首页",
                icon:"s-home",
                url:'Home/Home'
            },
        ],  //面包屑数据
        menu:[]
    },
    mutations:{
        //   修改菜单展开收起的方法
        collapseMenu(state){
            state.isCollapse=!state.isCollapse
        },
        //更新面包屑
        selectMenu(state,val){
            //判断添加的数据是否为首页
            if(val.name!=='home'){
                // console.log("state",state)
                const index=state.tabsList.findIndex(item=>item.name===val.name)
                //如果不存在
                if(index===-1){
                    state.tabsList.push(val)
                }
            }
        },
        //删除指定的tag
        closeTag(state,item){
            const index=state.tabsList.findIndex(val=>val.name===item.name)
            state.tabsList.splice(index,1)   //splice(删除的位置,删除的个数)
        },
        //设置menu的数据
        setMenu(state,val){
            state.menu=val
            console.log("val",val)
            Cookie.set('menu',JSON.stringify(val))
        },
        //动态注册路由
        addMenu(state,router){
            //判断缓存中是否有数据
            if(!Cookie.get('menu')) return
            const menu=JSON.parse(Cookie.get('menu'))
            state.menu=menu
            //组装动态路由的数据
            const menuArray=[]
            menu.forEach(item=>{
                if(item.children){
                    item.children= item.children.map(item=>{
                        item.component=()=>import(`../pages/${item.url}`)
                        return item
                    })
                    menuArray.push(...item.children)
                }else{
                    item.component=()=>import(`../pages/${item.url}`)
                    menuArray.push(item)
                }
            })
            console.log("menuArray",menuArray)
            //路由的动态添加
            menuArray.forEach(item=>{
                router.addRoute('main',item)
            })
            console.log("menuArray",menuArray)
        }
    }
}

Login.vue

getMenu(this.form).then(({data})=>{
            console.log(data)
            if(data.code===20000){
              Cookie.set('token',data.data.token)
              //获取菜单的数据,存入store中
              this.$store.commit('setMenu',data.data.menu)
              this.$store.commit('addMenu',this.$router)
              //跳转到首页
              this.$router.push('/home')
            }else{
              this.$message.error(data.data.message)
            }
          })

全部代码:

<template>
  <div id="app">
    <div class="main-content">
      <div class="title">系统登录</div>
      <div class="content">
        <el-form label-width="70px" :inline="true" :model="form" status-icon :rules="rules" ref="ruleForm" class="demo-ruleForm">
          <el-form-item label="用户名" prop="username">
            <el-input v-model="form.username" placeholder="请输入账号"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input v-model="form.password" type="password" autocomplete="off" placeholder="请输入密码"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button></el-col>
          </el-form-item>
        </el-form>
      </div>
    </div>

  </div>

</template>

<script>
// import Mock from 'mockjs'
import Cookie from 'js-cookie'
import {getMenu} from "@/api";
export default {
  name: "login",
  data(){
    return{
      form: {
        username: '',
        password:""
      },
      rules: {
        username: [
          {required: true, message: '请输入用户名', trigger: 'blur'},
        ],
        password: [
          {required:true,message:"请输入密码",trigger:"blur"}
        ]
      }
    }
  },
  methods:{
    //登录
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          //token信息
          /*const token=Mock.Random.guid()  //生成随机数
          //token信息存入cookie用于不同页面间的通信
          Cookie.set('token',token)*/
          getMenu(this.form).then(({data})=>{
            console.log(data)
            if(data.code===20000){
              Cookie.set('token',data.data.token)
              //获取菜单的数据,存入store中
              this.$store.commit('setMenu',data.data.menu)
              this.$store.commit('addMenu',this.$router)
              //跳转到首页
              this.$router.push('/home')
            }else{
              this.$message.error(data.data.message)
            }
          })

        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
  }
}
</script>

<style lang="less" scoped>
#app {
  display: flex;
  background-color: #333;
  height: 100vh;
  .main-content{
    height: 300px;
    width: 350px;
    //line-height: 100vh;
    background-color: #fff;
    margin: 200px auto;
    border-radius: 15px;
    padding: 35px 35px 15px 35px;
    box-sizing: border-box;
    box-shadow: 5px  5px 10px rgba(0,0,0,0.5),-5px -5px 10px rgba(0,0,0,0.5);
    .title{
      font-size: 20px;
      text-align: center;
      font-weight: 300;
    }
    .content{
      margin-top: 30px;
    }
    .el-input{
      width: 198px;
    }
    .el-button{
      margin-left: 105px;
    }
  }
}
</style>

CommonAside.vue

data() {
    return {
    };
  },
menuData(){
      //判断当前数据,如果缓存中没有,当前store中获取
      return JSON.parse(Cookie.get('menu'))||this.$store.state.tab.menu
    }

全部代码:

<template>
    <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
             :collapse="isCollapse" background-color="#545c64" text-color="#fff"
             active-text-color="#ffd04b">
      <h3>{{isCollapse?'后台':'通用后台管理系统'}}</h3>
      <el-menu-item @click="clickMenu(item)"  v-for="item in noChildren" :key="item.name" :index="item.name">
        <i :class="`el-icon-${item.icon}`"></i>
        <span slot="title">{{item.label}}</span>
      </el-menu-item>
      <el-submenu :index="item.label" v-for="item in hasChildren" :key="item.label">
        <template slot="title">
          <i :class="`el-icon-${item.icon}`"></i>
          <span slot="title">{{item.label}}</span>
        </template>
        <el-menu-item-group>
          <el-menu-item @click="clickMenu(subItem)" :index="subItem.path" :key="subItem.path" v-for="subItem in item.children">
            {{subItem.label}}
          </el-menu-item>
        </el-menu-item-group>
      </el-submenu>
    </el-menu>

</template>



<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
.el-menu{
  height: 100vh;  //占据页面高度100%
  h3{
    color: #fff;
    text-align: center;
    line-height: 48px;
    font-size: 16px;
    font-weight: 400;
  }
}
</style>

<script>
import Cookie  from "js-cookie";
export default {
  data() {
    return {
    };
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    clickMenu(item){
      // console.log(item)
      // console.log(this.$route.path)
      // 当页面的路由与跳转的路由不一致才允许跳转
      if(this.$route.path!==item.path && !(this.$route.path==='/home'&&(item.path==='/'))){
        this.$router.push(item.path)
      }
      this.$store.commit('selectMenu',item)
    }
  },
  mounted() {
    // console.log(this.$route.path)
  },
  computed:{
    //没有子菜单的数据
    noChildren(){
      return this.menuData.filter(item=>!item.children)
    },
    //有子菜单数组
    hasChildren(){
      return this.menuData.filter(item=>item.children)
    },
    isCollapse(){
      return this.$store.state.tab.isCollapse
    },
    menuData(){
      //判断当前数据,如果缓存中没有,当前store中获取
      return JSON.parse(Cookie.get('menu'))||this.$store.state.tab.menu
    }

  }
}
</script>

router/index.js

{
            // 子路由
            name:"main",
            path:'/',
            redirect:"/home",  //重定向 当路径为/,则重定向home
            component:Main,
            children:[
                    /*{
                        name:"user",
                        path:"user",
                        component:User,
                        meta:{title:"用户管理"}
                    },
                    {
                        name:"home",
                        path:"home",
                        component:Home,
                        meta:{title:"首页"}
                    },
                    {
                        name:"mall",
                        path:"mall",
                        component:Mall,
                        meta:{title:"商品管理"}
                    },
                    {
                        name:"page1",
                        path:"page1",
                        component:PageOne,
                        meta:{title:"页面1"}
                    },
                    {
                        name:"page2",
                        path:"page2",
                        component:PageTwo,
                        meta:{title:"页面2"}
                    }*/
            ]
        }

全部代码:

import VueRouter from "vue-router";
import Login from "@/pages/Login.vue";
import Main from '@/pages/Main.vue';
import User from "@/pages/User.vue";
import Home from "@/pages/Home.vue";
import Mall from "@/pages/Mall.vue";
import PageOne from "@/pages/PageOne.vue";
import PageTwo from "@/pages/PageTwo.vue";
import Cookie from "js-cookie";

const router= new VueRouter({
    // 浏览器模式设置,设置为history模式
    // mode:'history',
    routes:[
        {
            name:'login',
            path:"/login",
            component:Login,
            meta:{title:"登录"},
        },
        {
            // 子路由
            name:"main",
            path:'/',
            redirect:"/home",  //重定向 当路径为/,则重定向home
            component:Main,
            children:[
                    /*{
                        name:"user",
                        path:"user",
                        component:User,
                        meta:{title:"用户管理"}
                    },
                    {
                        name:"home",
                        path:"home",
                        component:Home,
                        meta:{title:"首页"}
                    },
                    {
                        name:"mall",
                        path:"mall",
                        component:Mall,
                        meta:{title:"商品管理"}
                    },
                    {
                        name:"page1",
                        path:"page1",
                        component:PageOne,
                        meta:{title:"页面1"}
                    },
                    {
                        name:"page2",
                        path:"page2",
                        component:PageTwo,
                        meta:{title:"页面2"}
                    }*/
            ]
        }

    ]
})
//添加全局前置导航守卫
router.beforeEach((to,from,next)=>{
    //判断token存不存在
    const token=Cookie.get('token')
    //token不存在,说明当前用户是未登录,应该跳转至登录页
    if(!token&&to.name!=='login'){
        next({name:'login'})
    }else if(token && to.name=="login"){   //token存在,说明用户登录,此时跳转至首页
        next({name:'home'})
    }else{
        next()
    }
})
// 后置路由守卫
router.afterEach((to,from)=>{
    document.title=to.meta.title||"通用后台管理系统"
})
export default router

请添加图片描述

权限管理问题解决

router/tab.js

clearTabs(state){
            //清除除过首页之外的所有面包屑
            state.tabsList=state.tabsList.splice(0,1)
        }

全部代码:

import Cookie from "js-cookie";
export default {
    state:{
        isCollapse:false,  //控制菜单的展开还是收起
        tabsList:[
            {
                path:'/',
                name:"home",
                label:"首页",
                icon:"s-home",
                url:'Home/Home'
            },
        ],  //面包屑数据
        menu:[]
    },
    mutations:{
        //   修改菜单展开收起的方法
        collapseMenu(state){
            state.isCollapse=!state.isCollapse
        },
        //更新面包屑
        selectMenu(state,val){
            //判断添加的数据是否为首页
            if(val.name!=='home'){
                // console.log("state",state)
                const index=state.tabsList.findIndex(item=>item.name===val.name)
                //如果不存在
                if(index===-1){
                    state.tabsList.push(val)
                }
            }
        },
        //删除指定的tag
        closeTag(state,item){
            const index=state.tabsList.findIndex(val=>val.name===item.name)
            state.tabsList.splice(index,1)   //splice(删除的位置,删除的个数)
        },
        //设置menu的数据
        setMenu(state,val){
            state.menu=val
            console.log("val",val)
            Cookie.set('menu',JSON.stringify(val))
        },
        //动态注册路由
        addMenu(state,router){
            //判断缓存中是否有数据
            if(!Cookie.get('menu')) return
            const menu=JSON.parse(Cookie.get('menu'))
            state.menu=menu
            //组装动态路由的数据
            const menuArray=[]
            menu.forEach(item=>{
                if(item.children){
                    item.children= item.children.map(item=>{
                        item.component=()=>import(`../pages/${item.url}`)
                        return item
                    })
                    menuArray.push(...item.children)
                }else{
                    item.component=()=>import(`../pages/${item.url}`)
                    menuArray.push(item)
                }
            })
            console.log("menuArray",menuArray)
            //路由的动态添加
            menuArray.forEach(item=>{
                router.addRoute('main',item)
            })
            console.log("menuArray",menuArray)
        },
        clearTabs(state){
            //清除除过首页之外的所有面包屑
            state.tabsList=state.tabsList.splice(0,1)
        }
    }
}

CommonHeader.vue

handleClick(command){
      if(command==='cancel'){
        console.log("登出")
        //清除Cookie的token信息
        Cookie.remove('token')
        //清除cookie中的menu
        Cookie.remove('menu')
        this.$store.commit('clearTabs')
        this.$router.push('/login')
      }

    }

全部代码:

<template>
  <div class="header-container">
    <div class="l-content">
      <el-button style="margin-right: 20px" icon="el-icon-menu" size="mini" @click="handleMenu"></el-button>
      <!--      面包屑-->
<!--      <span class="text">首页</span>-->
      <el-breadcrumb separator="/">
        <el-breadcrumb-item v-for="item in tags" :key="item.path" :to="{ path: item.path }">{{ item.label }}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <div class="r-content">
      <el-dropdown @command="handleClick">
          <span class="el-dropdown-link">
            <img src="@/assets/user.webp" alt="">
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>个人中心</el-dropdown-item>
            <el-dropdown-item command="cancel">退出</el-dropdown-item>
          </el-dropdown-menu>
      </el-dropdown>
    </div>
  </div>

</template>

<script>
import {mapState} from 'vuex'
import Cookie from 'js-cookie'
export default {
  name: "CommonHeader",
  methods:{
    handleMenu(){
      this.$store.commit('collapseMenu')
    },
    handleClick(command){
      if(command==='cancel'){
        console.log("登出")
        //清除Cookie的token信息
        Cookie.remove('token')
        //清除cookie中的menu
        Cookie.remove('menu')
        this.$store.commit('clearTabs')
        this.$router.push('/login')
      }

    }
  },
  computed:{
    ...mapState({
      tags: state=>state.tab.tabsList
    })
  }
}
</script>

<style scoped lang="less">
.header-container {
  height: 60px;
  background-color: #333;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;

  .text {
    color: #fff;
    font-size: 14px;
    margin-left: 10px;
  }
  .r-content{
    img{
      width: 40px;
      height: 40px;
      border-radius: 50%;
    }
  }
  .l-content{
    display: flex;
    align-items: center;
    /deep/.el-breadcrumb__item{   /*元素没有绑定data-v-5a90ec03这样的编号时候,样式不起作用,使用deep进行穿刺可解决问题*/
      .el-breadcrumb__inner{
        font-weight: normal;
        &.is-link{
          color: #666;
        }
      }
      &:last-child{
        .el-breadcrumb__inner {
          color: #fff;
        }
      }
    }
  }
}
</style>

main.js

created(){
    store.commit('addMenu',router)
  }

全部代码:

import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import router from "@/router";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
import store from '@/store'
//引入mock模拟
import '@/api/mock'

Vue.config.productionTip = false
Vue.use(VueRouter)
Vue.use(ElementUI)
new Vue({
  store,
  router,
  render: h => h(App),
  created(){
    store.commit('addMenu',router)
  }
}).$mount('#app')

请添加图片描述

项目到此Vue2部分也就结束了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/987654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 通过自定义控件实现炫酷的时间显示

先看效果 话不多说,直接上代码 基础的自定义控件 LED_Num public partial class LED_Num : UserControl{#region 属性/// <summary>/// 绘图区域/// </summary>Rectangle DrawArea = Rectangle.

Linux系统——MySQL安装与卸载(CentOS7 超详细演示)

Linux系统 安装与卸载 MySQL—— 超详细演示! MySQL8.0.26-Linux版安装1. 准备一台Linux服务器2. 下载Linux版MySQL安装包3. 上传MySQL安装包4. 创建目录,并解压5. 安装mysql的安装包6. 启动MySQL服务7. 查询自动生成的root用户密码8. 修改root用户密码9. 创建用户10. 并给root…

安卓手机怎么录屏?看这里,小白也能学会

“安卓手机可以录屏吗&#xff1f;最近需要用到录屏功能&#xff0c;在手机里面找了很久&#xff0c;也没有找到&#xff0c;听别人说安卓手机是有录屏的&#xff0c;有人知道怎么打开吗&#xff1f;” 在日常生活中&#xff0c;我们常常需要录制手机屏幕上的操作步骤&#xf…

QQ通讯录在哪里?3个步骤教你查找

QQ是一个综合性通讯平台&#xff0c;简单实用&#xff0c;并且具有许多令人喜爱的特点和优势。它给大家提供了丰富的功能和便利的交流方式&#xff0c;丰富了人们的日常生活。作为一款人们常用的聊天软件&#xff0c;其qq通讯录在哪里呢&#xff1f;本文将以苹果手机为例&#…

产品路线图如何制定?斯坦福大学产品管理课程为你支招

产品路线图是一个动态文档&#xff0c;它传达了与产品策略有关的项目清单及其优先次序。一个合格的产品路线图依赖哪些输入&#xff1f;又需要清晰地输出哪些信息&#xff1f; 本篇文章将与你分享&#xff0c;我在斯坦福大学「产品管理加速课程」中习得的产品路线图制定方法。…

抖音无需API开发连接Stable Diffusion,实现自动根据评论区的指令生成图像并返回

抖音用户使用场景&#xff1a; 随着AI绘图的热度不断升高&#xff0c;许多抖音达人通过录制视频介绍不同的AI工具&#xff0c;包括产品背景、使用方法以及价格等&#xff0c;以吸引更多的用户。其中&#xff0c;Stable Diffusion这款产品受到了许多博主达人的青睐。在介绍这款产…

git-命令行显示当前目录分支

搜索家目录.bashrc隐藏文件&#xff0c;找到如下内容 forlinxubuntu:~$ vi .bashrcif [ "$color_prompt" yes ]; thenPS1${debian_chroot:($debian_chroot)}\[\033[01;32m\]\u\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ elsePS1${debian_chroot:($debian_ch…

气传导耳机什么牌子好?盘点五款好用的气传导耳机分享

​对于气传导耳机&#xff0c;大家最关心的可能是佩戴会不会不舒服&#xff1f;音质好不好&#xff1f;会不会漏音&#xff1f;等问题。面对这些问题&#xff0c;今天我就为大家推荐几款市面上最好的气传导耳机&#xff0c;总有一款适合你的&#xff01; ①NANK南卡00压气传导…

一次预制体丢失[XX prefab at index n is missing]的排查经历 及 【用代码查找场景中的预制体】

一、症状描述 &#xff08;1&#xff09;从【主场景】跳转【某场景】时&#xff0c;报错——预制体丢失[prefab is missing] &#xff08;2&#xff09;在编辑器单独启动该场景&#xff0c;没有报错 二、症状溯源 场景里面有预制体实例&#xff0c;但是我把预制体的资源删除…

脚本:python实现樱花树

文章目录 代码效果 代码 from turtle import * from random import * from math import * def tree(n, l):pd () # 下笔# 阴影效果t cos ( radians ( heading () 45 ) ) / 8 0.25pencolor ( t, t, t )pensize ( n / 3 )forward ( l ) # 画树枝if n > 0:b random () *…

算法训练营day44|动态规划 part06:完全背包 (完全背包、 LeetCode518. 零钱兑换 II、377. 组合总和 Ⅳ )

文章目录 完全背包518. 零钱兑换 II思路分析代码实现思考总结 377. 组合总和 Ⅳ思路分析代码实现思考总结 完全背包 完全背包和01背包问题唯一不同的地方就是&#xff0c;每种物品有无限件。 依然举这个例子&#xff1a; 背包最大重量为4。 物品为&#xff1a; 重量价值物品…

电工-什么是电压

什么是电压&#xff1f;电压计算公式和单位换算及电位差概念讲解 前面第一课中学过电路的组成&#xff0c;而第二课中介绍了电流的一些基本概念、计算公式和单位换算&#xff0c;然而我们在电路等用电的地方还听到过电压这个概念&#xff0c;本文就给大家介绍什么是电压及电压…

【校招VIP】产品功能设计之思维创意考察

考点介绍&#xff1a; 在产品设计的过程中&#xff0c;为了解决用户在产品使用过程中的问题&#xff0c;或者想让产品相比于竞品更加与众不同&#xff0c;那就需要有创意思维。创意是一种通过创新思维意识&#xff0c;来挖掘资源组合方式从而提升资源价值的方法。 产品功能设计…

【django】Forbidden (CSRF cookie not set.)

CSRF 表示django全局发送post请求均需要字符串验证 功能&#xff1a; 防止跨站请求伪造的功能 工作原理&#xff1a; 客户端访问服务器端&#xff0c;在服务器端正常返回给客户端数据的时候&#xff0c;而外返回给客户端一段字符串&#xff0c;等到客户端下次访问服务器端时…

正中优配:股票顶部形态有哪些?

股票顶部形状是投资者们在炒股中必备的技术之一&#xff0c;它是指股票价格上涨到最高点之后开始跌落的形状。因而&#xff0c;判断股票顶部形状十分有必要&#xff0c;能够协助投资者采纳正确的交易战略&#xff0c;避免经济损失。本文将从多个视点分析股票顶部形状&#xff0…

Arthas 排查JVM问题总结

一、安装 在Arthas官网&#xff1a;https://arthas.aliyun.com/中下载安装包。 执行java -jar arthas-boot.jar就可以启动。 二、常见命令 dashboard&#xff1a;查看JVM全局概览&#xff0c;包括线程、堆内存、GC还有系统信息等 thread&#xff1a;常见命令&#xff0c;查看…

【JS进阶】防抖与节流

防抖与节流 1.防抖 1.1 为什么要防抖&#xff1f; 在项目中&#xff0c;有的操作是高频触发的&#xff0c;但是其实触发一次就好了&#xff0c;比如我们短时间内多次缩放页面&#xff0c;那么我们不应该每次缩放都去执行操作&#xff0c;应该只做一次就好。再比如说监听输入…

视频直播点播平台EasyDSS视频云平台播放器码率显示不全的原因及其解决办法

EasyDSS互联网视频云平台可提供一站式的视频转码、点播、直播、推拉流、时移回放等服务&#xff0c;也能支持4K视频的直播、点播等功能。EasyDSS可用于视频点播&#xff0c;并支持OBS、推流相机、EasyRTMP等设备的推流直播&#xff0c;可应用在AR、VR、无人机推流、虚拟直播、教…

Word文档超过了20MB如何缩小?文件压缩这样做

在现代办公中&#xff0c;我们常常会遇到各种大小的Word文档&#xff0c;而当一个文档大小超过20MB时&#xff0c;无论是发送还是接收&#xff0c;都会带来诸多不便。那么&#xff0c;如何将过大的Word文档缩小呢&#xff1f;下面&#xff0c;就给大家分享几个简单且实用的方法…

【面试心得】WebBench 整理

在面试九识的时候&#xff0c;被问到了WebBench的原理&#xff0c;当时没答上来&#xff0c;这里做一个整理 WebBench 源码【带注释】&#xff1a;GitHub - YukunJ/annotated-webbench-1.5: bilingually annotated Webbench-1.5 webbench是一个轻量的压测工具&#xff0c;可以…