web开发:如何用Echarts来自动给网页设计各种统计图

news2024/9/23 11:16:11

很多时候web开发也会需要用到统计图,如果单纯靠我们自己那点拙劣的css和js水平设计的话,又耗时间又做得跟史一样,这时候就需要引入别人设计师为我们设计好的动态统计图——echarts

Echarts的官网是:Apache ECharts

1、第一步:引入echarts

跟引入bootstrap、Vue这些一样,你可以选择引入本地的js文件,或者用在线的CDN

本地的文件在本文顶部开头中,自己下载。如果找不到我的资源可以下载这个链接https://registry.npmjs.org/echarts/-/echarts-5.5.0.tgz,解压后找到【dist】文件夹,找到【echarts.js】文件,把它解压到你要用它的同级目录下,然后引入本地js文件到html中

<!-- 引入刚刚下载的 ECharts 文件 -->
<script src="echarts.js"></script>

或者不要那么麻烦,直接用在线CDN,我更偏向这种,把这段代码写到你的html文件里

<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>

2、第二步,为echarts统计图表设置一个固定宽度和高度的容器

例如:

<!-- css部分 -->
<style>
.echarts-box {
    width: 600px;
    height: 400px;
    padding: 30px;
    margin: 0 auto;
    border: 1px solid #ccc;
  }
</style>

<!-- HTML部分 -->
<body>
  <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
  <div class="echarts-box" id="main"></div>
</body>

3、然后直接开始CV大法,乱用爽用

点开【示例】,会看到各种花里胡哨的图,直接选择自己喜欢的点击,样例代码都给你了,直接开始cv

但是它代码提供的只是这个样例的代码,并没有提供我们怎么去创建它并开启它的代码,要我们手动开启,也很简单:

1、echarts.init( )函数是开始创建这个样例的容器,你上面HTML已经写了一个容器了,那么现在echarts需要知道那个容器是用来存放、展示echarts图表的,你只需要用JavaScript绑定这个DOM元素然后传参给echarts.init( )函数就行了

let myChart = echarts.init(document.getElementById('main'));

2、通过【echars容器变量.setOption( )】函数显示图表

.setOption()函数需要往里传入配置数据参数,这个【配置数据参数】就是你刚刚网页上copy的那一堆代码,你可以直接copy到.setOption()里;也可以用一个变量等于你刚刚那一堆配置数据,然后再把变量放进.setOption()里

// 指定图表的配置项和数据
//这个案例是柱状图
let option = {
    title: {
    text: 'ECharts柱状图示例'
    },
    tooltip: {},
    legend: {
    data: ['销量']
    },
    xAxis: {
    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [
    {
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
    }
    ]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);

下面代码是两个完整的例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    .echarts-box {
        width: 600px;
        height: 400px;
        padding: 30px;
        margin: 0 auto;
        border: 1px solid #ccc;
      }
    </style>
</head>
<body>
    <div class="echarts-box" id="main"></div>
    <div class="echarts-box No2" id="main"></div>

    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        let myChart = echarts.init(document.getElementById('main'));
  
        // 指定图表的配置项和数据
        //这个案例是柱状图
        let option = {
            title: {
            text: 'ECharts柱状图示例'
            },
            tooltip: {},
            legend: {
            data: ['销量']
            },
            xAxis: {
            data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {},
            series: [
            {
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }
            ]
        };
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);


        //这个案例是圆饼图
        let myChart2 = echarts.init(document.querySelector('.No2'))
        let option2 = {
            title: {
                text: '岑梓铭的圆饼图',
                subtext: '靓不靓啊?',
                left: 'center'
            },
            tooltip: {
                trigger: 'item'
            },
            legend: {
                orient: 'vertical',
                left: 'left'
            },
            series: [
                {
                name: 'Access From',
                type: 'pie',
                radius: '50%',
                data: [
                    { value: 1048, name: '吃饭' },
                    { value: 735, name: '睡觉' },
                    { value: 580, name: '玩手机' },
                    { value: 484, name: '学习' },
                    { value: 300, name: '看美女' }
                ],
                emphasis: {
                    itemStyle: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
                }
            ]
        };
        myChart2.setOption(option2)
      </script>
</body>
</html>

具体你需要配置什么标题、解释文字、颜色,这些你可以直接在在线示例里修改它的代码,然后慢慢找代码的哪个地方对应图表的哪个地方

具体例子还可以到这个网站去看看:echarts官网 | 中文官网

另外,在Vue中使用echart图表的话,建议刚刚那些代码写在mounted( )函数里,这样的话根据option里的配置数据(或者是绑定了data里的初始数据),当页面刚进入就能看到一个初始的图表样子。

mounted () {
  let myChart = echarts.init(document.querySelector('#main'))
  myChart.setOption({
    // 大标题
    title: {
      text: '消费账单列表',
      left: 'center'
    },
    // 提示框
    tooltip: {
      trigger: 'item'
    },
    // 图例
    legend: {
      orient: 'vertical',
      left: 'left'
    },
    // 数据项
    series: [
      {
        name: '消费账单',
        type: 'pie',
        radius: '50%', // 半径
        data: [
          { value: 1048, name: '球鞋' },
          { value: 735, name: '防晒霜' }
        ],
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }
    ]
  })
},

那么如果你要动态更新的话,只需要在Vue的methods函数配置项里设置一个函数,在这个函数里再次.setOption( )就可以了动态更新了。

但是这里有一个需要注意的:你在methods的函数里设置.setOption( ),说明你已经离开mounted函数了,那就拿不到【代表echarts图表的容器】了,那怎么setOption呢?记住一点:只要要在Vue里想全局使用某个变量,就把他挂到data里。那么这里也可以把【代表echarts图表的容器】挂到data

上面的例子改一下(数据配置啥的代码省略了,一样的):

data: {
  //挂载的全局变量
  list: [],
  name: '',
  price: ''
},
computed: {
  某函数 () {
    return 统计结果
  }
},
created () {
  //做一些网络数据请求、数据操作
},
mounted () {
  //直接一个【this.变量】,甚至都不用在data里设置变量,就可以到处用它了
  this.myChart = echarts.init(document.querySelector('#main'))
  this.myChart.setOption({
    //echarts的数据配置
  })
},

现在再拿【this.变量】去setOption()就可以更新图表了

methods: {
    // 更新图表
    // 现在就可以用this.myChart去调用setOption()了
    this.myChart.setOption({
      // 其他项可以不用复制过来,只用设置要修改的数据项就好了
      // 数据项
      series: [
        {
          // 这里也不是一个一个数据写好去配置,而是采用动态配置
          // data: [
          //   { value: 1048, name: '球鞋' },
          //   { value: 735, name: '防晒霜' }
          // ]
          data: this.list.map(item => ({ value: item.price, name: item.name}))
          //这里先解释一下.map()函数是什么意思
          //.map()函数是遍历数组每个成员,然后return一个经过修改的值,作为遍历到的这个成员的新值
          //item是自定义的,代表遍历到的数组的每一个成员
          //然后()=>箭头函数如果是一个值、一句话、一个表达式,就代表这就是要return的内容
          //例子中:{ value: item.price, name: item.name }就是return这么一个对象值
          //为什么用()包住这个对象?因为对象外层是{},箭头函数会当成这是一个函数体,要用()包起来

          //然后为什么要修改list数组的值?
          //因为前面我们把网络数据返回的内容给到了data设的数组list
          //然后我们要去用console.log()检查这些数据有什么内容,哪些有用要,哪些没用不要
          //然后发现echarts需要的data的配置参数只有value和name这两个参数
          //那我们就只提取出list的每一个对象成员的符合value和name这两个参数要的值
          //然后把list的每一个对象成员设置成{ value: xxx, name: xxx }这种形式,就符合echarts示例所需要得到配置参数要求了
        }
      ]
    })
},

这里先解释一下.map()函数是什么意思
.map()函数是遍历数组每个成员,然后return一个经过修改的值,作为遍历到的这个成员的新值。item是自定义的,代表遍历到的数组的每一个成员
然后()=>箭头函数如果是一个值、一句话、一个表达式,就代表这就是要return的内容
例子中:{ value: item.price, name: item.name }就是return这么一个对象值
为什么用()包住这个对象?因为对象外层是{},箭头函数会当成这是一个函数体,要用()包起来

然后为什么要修改list数组的值?
因为前面我们把网络数据返回的内容给到了data设的数组list,然后我们要去用console.log()检查这些数据有什么内容,哪些有用要,哪些没用不要
然后发现echarts需要的data的配置参数只有value和name这两个参数,那我们就只提取出list的每一个对象成员的符合value和name这两个参数要的值
然后把list的每一个对象成员设置成{ value: xxx, name: xxx }这种形式,就符合echarts示例所需要得到配置参数要求了

兄弟们我解释得很透彻很幸苦,各位好好看,点个赞

另外把整个例子完整代码放这里:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- CSS only -->
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
    />
    <style>
      .red {
        color: red!important;
      }
      .search {
        width: 300px;
        margin: 20px 0;
      }
      .my-form {
        display: flex;
        margin: 20px 0;
      }
      .my-form input {
        flex: 1;
        margin-right: 20px;
      }
      .table > :not(:first-child) {
        border-top: none;
      }
      .contain {
        display: flex;
        padding: 10px;
      }
      .list-box {
        flex: 1;
        padding: 0 30px;
      }
      .list-box  a {
        text-decoration: none;
      }
      .echarts-box {
        width: 600px;
        height: 400px;
        padding: 30px;
        margin: 0 auto;
        border: 1px solid #ccc;
      }
      tfoot {
        font-weight: bold;
      }
      @media screen and (max-width: 1000px) {
        .contain {
          flex-wrap: wrap;
        }
        .list-box {
          width: 100%;
        }
        .echarts-box {
          margin-top: 30px;
        }
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="contain">
        <!-- 左侧列表 -->
        <div class="list-box">

          <!-- 添加资产 -->
          <form class="my-form">
            <input v-model.trim="name" type="text" class="form-control" placeholder="消费名称" />
            <input v-model.number="price" type="text" class="form-control" placeholder="消费价格" />
            <button @click="add" type="button" class="btn btn-primary">添加账单</button>
          </form>

          <table class="table table-hover">
            <thead>
              <tr>
                <th>编号</th>
                <th>消费名称</th>
                <th>消费价格</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(item, index) in list" :key="item.id">
                <td>{{ index + 1 }}</td>
                <td>{{ item.name }}</td>
                <td :class="{ red: item.price > 500 }">{{ item.price.toFixed(2) }}</td>
                <td><a @click="del(item.id)" href="javascript:;">删除</a></td>
              </tr>
            </tbody>
            <tfoot>
              <tr>
                <td colspan="4">消费总计: {{ totalPrice.toFixed(2) }}</td>
              </tr>
            </tfoot>
          </table>
        </div>
        
        <!-- 右侧图表 -->
        <div class="echarts-box" id="main"></div>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
      /**
       * 接口文档地址:
       * https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058
       * 
       * 功能需求:
       * 1. 基本渲染
       *    (1) 立刻发送请求获取数据 created
       *    (2) 拿到数据,存到data的响应式数据中
       *    (3) 结合数据,进行渲染 v-for
       *    (4) 消费统计 => 计算属性
       * 2. 添加功能
       *    (1) 收集表单数据 v-model
       *    (2) 给添加按钮注册点击事件,发送添加请求
       *    (3) 需要重新渲染
       * 3. 删除功能
       *    (1) 注册点击事件,传参传 id
       *    (2) 根据 id 发送删除请求
       *    (3) 需要重新渲染
       * 4. 饼图渲染
       *    (1) 初始化一个饼图 echarts.init(dom)  mounted钩子实现
       *    (2) 根据数据实时更新饼图 echarts.setOption({ ... })
       */
      const app = new Vue({
        el: '#app',
        data: {
          list: [],
          name: '',
          price: ''
        },
        computed: {
          totalPrice () {
            return this.list.reduce((sum, item) => sum + item.price, 0)
          }
        },
        created () {
          // const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
          //   params: {
          //     creator: '小黑'
          //   }
          // })
          // this.list = res.data.data

          this.getList()
        },
        mounted () {
          this.myChart = echarts.init(document.querySelector('#main'))
          this.myChart.setOption({
            // 大标题
            title: {
              text: '消费账单列表',
              left: 'center'
            },
            // 提示框
            tooltip: {
              trigger: 'item'
            },
            // 图例
            legend: {
              orient: 'vertical',
              left: 'left'
            },
            // 数据项
            series: [
              {
                name: '消费账单',
                type: 'pie',
                radius: '50%', // 半径
                data:[
                  { value: 1048, name: '球鞋' },
                  { value: 735, name: '防晒霜' }
                ],
                emphasis: {
                  itemStyle: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                  }
                }
              }
            ]
          })
        },

        methods: {
          async getList () {
            const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
              params: {
                creator: '小黑'
              }
            })
            this.list = res.data.data
            console.log(res.data.data)
            console.log(this.list)

            // 更新图表
            this.myChart.setOption({
              // 数据项
              series: [
                {
                  // data: [
                  //   { value: 1048, name: '球鞋' },
                  //   { value: 735, name: '防晒霜' }
                  // ]
                  data: this.list.map(item => ({ value: item.price, name: item.name}))
                  //这里这么写是因为
                  //看echarts的这个示例的源码的配置数据可以知道,在这个配置数据的data这里只能有value和name这两个参数
                  //然后我们console.log可以看到我们拿到的对象数据里很乱,什么值都有,但是没有value这个参数名(name刚好有)
                  //但是我们打印输出可以注意到,对象里的price值就对应着value要的值,name值对应name要的值
                  //那么只是名字不一样,而且还有别的多余的参数,那就把获取到对象数据的list数组修改一下里面的内容
                  //用map函数,item是自定义的,代表遍历到数组的每一个成员,那么item.price不就是这个对象成员的price项吗
                  //这样一来list数组每个对象成员就变成{ value: xxx, name: xxx }这种形式了,就符合echarts示例所需要得到配置参数要求了
                }
              ]
            })
          },
          async add () {
            console.log(this.list)
            if (!this.name) {
              alert('请输入消费名称')
              return
            }
            if (typeof this.price !== 'number') {
              alert('请输入正确的消费价格')
              return
            }

            // 发送添加请求
            const res = await axios.post('https://applet-base-api-t.itheima.net/bill', {
              creator: '小黑',
              name: this.name,
              price: this.price
            })
            // 重新渲染一次
            this.getList()

            this.name = ''
            this.price = ''
          },
          async del (id) {
            // 根据 id 发送删除请求
            const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
            // 重新渲染
            this.getList()
          }
        }
      })
    </script>
  </body>
</html>

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

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

相关文章

一个脚本两步计算材料Raman谱(附数据处理和绘图脚本)

在以往推送中已经介绍了相当多的计算材料Raman的方法&#xff0c;使用的软件主要为Phonopy-Spectroscopy&#xff0c;相关软件还有vasp&#xff0c;phonopy&#xff0c;phono3py等。 Phonopy-Spectroscopy计算材料红外和Raman光谱 Phonopy-Spectroscopy 计算红外和拉曼光谱 也…

重学Springboot3-@ConditionalOnXxx条件注解

重学Springboot3-ConditionalOnXxx条件注解 引言常见的条件注解常见的条件注解示例扩展条件注解1. ConditionalOnJndi2. ConditionalOnJava3. ConditionalOnCloudPlatform4. ConditionalOnEnabledResourceChain5. 自定义条件注解 总结 引言 Spring Boot 提供了一组强大的条件注…

2.1 mov、add和sub加减指令实操体验

汇编语言 1. mov操作 1.1 mov移动值 mov指令把右边的值移动到左边 mount c d:masm c: debug r ax 0034 r 073f:0100 mov ax,7t1.2 mov移动寄存器的值 把右边寄存器的值赋值给左边的寄存器 a 073f:0105 mov bx,axt1.3 mov高八位&#xff08;high&#xff09;和低八位&am…

cetos7 Docker 安装 gitlab

一、gitlab 简单介绍和安装要求 官方文档&#xff1a;https://docs.gitlab.cn/jh/install/docker.html 1.1、gitlab 介绍 gitLab 是一个用于代码仓库管理系统的开源项目&#xff0c;使用git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务平台&#xff0c;通过该平…

C++_数据类型_布尔类型

作用 布尔数据类型代表真或假的值 bool类型只有两个值&#xff1a; ture 真&#xff08;本质是1&#xff09;false 假 &#xff08;本质是0&#xff09; bool类型占1个字节大小 示例 注意 bool类型&#xff0c;只要是非0的值都代表真

【谈一谈】我们所用的三种工厂模式优缺点

【谈一谈】我们所用的三种工厂模式优缺点 Hello!!大家好啊,好久也没有进行文章的更新了,原因嘛,最近的工作任务量有点大,导致摸鱼充电的时间大量减少,哈哈哈(你别说,这是借口嘛!) 不过,今天是星期六,难的能够在这里分享下最近在工作中,我用到的三种工厂模式(简工抽),有啥区别呢…

国内哪个工具可以平替chatgpt?国内有哪些比较好用的大模型gpt?

我自己试用了很多的平台&#xff0c;发现三个比较好的大模型平台&#xff0c;对普通用户也比较的友好的&#xff0c;而且返回内容相对来说&#xff0c;正确率更高的&#xff0c;并且相关场景插件比较丰富的国内厂商。 本文说的&#xff0c;是我自己觉得的&#xff0c;比较有主观…

linux之进程理解(1)

目录 1. 冯诺依曼体系结构 2. 操作系统(OS) 2.1 概念 2.2 设计OS的目的 2.3 定位 2.4 理解管理 3. 系统调用和库函数概念 4. 补充 1. 冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体…

HCIA-Datacom实验指导手册:8 网络编程与自动化基础

HCIA-Datacom实验指导手册&#xff1a;8 网络编程与自动化基础 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;步骤 1 完成交换机的 Telnet 预配置步骤 2 Python 代码编写 五、结果验证六、windows 计划任务程序配置七、 …

全部都有的子序列

思路&#xff08;双指针&#xff09; 先使用Set来存储总共有多少不同的数字&#xff0c;然后我们使用快慢指针去遍历数组&#xff0c;快指针每次遍历到一个数&#xff0c;将其加入到哈希表&#xff0c;哈希表使用pair存储&#xff0c;第一个元素存数字&#xff0c;第二个元素存…

2024最新算法:鳑鲏鱼优化算法(Bitterling Fish Optimization,BFO)求解23个基准函数(提供MATLAB代码)

一、鳑鲏鱼优化算法 鳑鲏鱼优化算法&#xff08;Bitterling Fish Optimization&#xff0c;BFO&#xff09;由Lida Zareian 等人于2024年提出。鳑鲏鱼在交配中&#xff0c;雄性和雌性物种相互接近&#xff0c;然后将精子和卵子释放到水中&#xff0c;但这种方法有一个很大的缺…

javaweb请求与响应

前言 前面介绍了对应的服务器端的相关代码。这里开始学习服务器端与客户端的数据请求与响应 这里的仅仅是一个简单的调用&#xff0c;并没有经过servelert接口来进行调用&#xff0c;同前面的一样&#xff0c;我们介绍对应的本地服务器进行的部署项目。 代码 //属于简单的不…

【Memory协议栈】Memory Abstraction Interface模块介绍

目录 前言 正文 1.功能简介 2.关键概念 3.关键类型定义 3.1 MemIf_StatusType 3.2 MemIf_JobResultType 3.3 MemIf_ModeType 4.关键API定义 4.1 MemIf_SetMode 4.2 MemIf_Read 4.3 MemIf_Write 4.4 MemIf_Cancel 4.5 MemIf_GetStatus 4.6 MemIf_GetJobResult 4…

2023年NOC大赛软件创意编程(学而思)赛道图形化小高组复赛试题

目录 第一题 闪烁的星星 第二题 聚沙成塔 第三题 画十字

#WEB前端(DIV、SPAN)

1.实验&#xff1a;DIV、SPAN 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; 类? 4.代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdev…

状态机设计原则系列之效率最大化

检测、搬运类设备,自动运行往往都设计状态机,搬运类对设备节拍往往要求很高,这里我们就需要合理的划分状态机了,使我们的执行效率最大化。有关状态机的系列文章可以查看下面相关文章链接: 1、机器流程控制之建立状态机 https://rxxw-control.blog.csdn.net/article/deta…

智能驾驶规划控制理论学习04-基于车辆运动学的规划方法

目录 一、线性二自由度汽车模型&#xff08;自行车模型&#xff09; 1、二自由度模型概述 2、不同参考点下的状态空间方程 3、前向仿真 二、运动基元生成方法 1、杜宾斯曲线&#xff08;Dubins Curve&#xff09; 2、Reeds Shepp Curve 三、多项式曲线&#xff08;Poly…

多线程(进阶四:线程安全的集合类)

目录 一、多线程环境使用ArrayList 二、多线程环境使用队列 三、多线程环境使用哈希表 1、HashMap 2、Hashtable 3、ConcurrentHashMap (1)缩小了锁的粒度 (2)充分使用了CAS原子操作&#xff0c;减少一些加锁 (3)针对扩容操作的一些优化&#xff08;化整为零&#xff…

优选算法|【双指针】283.移动零

题目 283. 移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12]输出: [1,3,12,0,0]示例 2: 输入…

基于ssm旅社客房收费管理系统+vue

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…