Vue时间轴 vue-light-timeline的用法说明


Posted in Javascript onOctober 29, 2020

轻量的vue时间轴组件

install

npm install vue-light-timeline

如果你使用的是yarn

yarn add vue-light-timeline

usage

import LightTimeline from 'vue-light-timeline';

Vue.use(LightTimeline);

<template>
 <light-timeline :items='items'></light-timeline>
</template>
 
export default {
 data () {
  return {
   items: [
    {
     tag: '2019-02-12',
     content: '测试内容'
    },
    {
     tag: '2019-02-13',
     type: 'circle',
     content: '练习内容'
    }
   ]
  }
 }
}

或者你还可以为时间轴的每个部分传递插槽:

<template>
 <light-timeline :items='items'>
  <template slot='tag' slot-scope='{ item }'>
   {{item.date}}
  </template>
  <template slot='content' slot-scope='{ item }'>
   {{item.msg}}
  </template>
 </light-timeline>
</template>
<script>
export default {
 data () {
  return {
   items: [
    {
     date: '2019-02-12',
     msg: '测试内容'
    },
    {
     date '2019-02-13',
     msg: '练习内容'
    }
   ]
  }
 }
}

Vue时间轴 vue-light-timeline的用法说明

自己写个好看点的样式就行了

补充知识:Vue可移动水平时间轴

里程碑时间轴具体实现

效果图

Vue时间轴 vue-light-timeline的用法说明

编辑里程碑效果图

Vue时间轴 vue-light-timeline的用法说明

<template>
<div class="state_grade">
<!--    <mile-stone :projectId="projectData.proId" :projectName="projectData.proName" :proNum="projectData.proNum"></mile-stone>-->
    <div class="timeLine" style="overflow: hidden;">
     <div style="width: 10%; display: inline-block; margin-left: 5px;">
      <el-button @click="mileStoUpdateVisible = true" type="primary">编辑里程碑</el-button>
     </div>
     <div style="width: 70%;display: inline-block" align="center">
      <div style="width: 20%;display: inline-block; font-size: 14px;">里程碑状态:</div>
      <div style="width: 100px;display: inline-block; font-size: 14px; ">开始 <img class="node_picture" src="../../assets/images/timeLineA.png"></div>

      <div style="width: 100px;display: inline-block; font-size: 14px;">超期 <img class="node_picture" src="../../assets/images/timeLineB.png"> </div>

      <div style="width: 100px;display: inline-block; font-size: 14px;">关闭 <img class="node_picture" src="../../assets/images/timeLineC.png"> </div>

     </div>

     <div class="my_timeline_prev" @click="moveLeft">
      <img src="../../assets/arrow_left_blue.png" class="my_timeline_node"/>
      <!--   <div class="my_timeline_item_line" style="margin-top: -18px;"></div>-->
      <!--   <div class="my_timeline_item_content" style="color: rgba(0,0,0,0);">上</div>-->
     </div>
     <div v-if="destroyIncomeStatistics" class="ul_box">
      <ul class="my_timeline" ref="mytimeline" style="margin-left: 10px;">
       <li class="my_timeline_item" v-for="(item,index) in timeLineList" :key="index">

        <el-tooltip placement="top" effect="light">
         <div slot="content" class="tooltip">
          <el-row>
           <el-col :span="24">{{'阶段名称:'+item.stageName}}</el-col>
          </el-row>
          <el-row>
           <el-col :span="24">{{'阶段目标:'+item.stageTarget}}</el-col>
          </el-row>
          <el-row>
           <el-col :span="24">{{'开始时间:'+item.startTime}}</el-col>
          </el-row>
          <el-row>
           <el-col :span="24">{{'结束时间:'+item.endTime}}</el-col>
          </el-row>
          <el-row>
           <el-col :span="24">{{'验收标准:'+item.acceptStar}}</el-col>
          </el-row>
          <el-row>
           <el-col :span="24">
            <span v-if="item.milepostState==='1'">里程碑状态:打开</span>
            <span v-if="item.milepostState==='2'">里程碑状态:超期</span>
            <span v-if="item.milepostState==='3'">里程碑状态:关闭</span>
           </el-col>
          </el-row>
         </div>
         <!--圈圈节点-->
         <!--       <div class="my_timeline_node" style="backgroundColor: #999; width: 28px;height: 28px;" @click="changeActive(index)" :class="{active: index == timeIndex}"></div>-->
         <div class="my_timeline_node">
          <div style="background-color: #FCFCFC">
           <img class="my_timeline_picture" v-if="item.milepostState==='1'"
              src="../../assets/images/timeLineA.png">
           <img class="my_timeline_picture" v-if="item.milepostState==='2'"
              src="../../assets/images/timeLineB.png">
           <img class="my_timeline_picture" v-if="item.milepostState==='3'"
              src="../../assets/images/timeLineC.png">
          </div>
         </div>
        </el-tooltip>
        <!--线-->
        <div
         :class="[timeLineList.length==index+1?my_timeline_item_line_last:my_timeline_item_line_not_last]"></div>
        <!--标注-->
        <div class="my_timeline_item_content">
         <div>{{item.endTime}}</div>
         <el-tooltip placement="top" effect="light">
          <div slot="content">{{item.endTime}}<br/>{{item.stageName}}</div>
          <div class="detail_info">{{item.stageName}}</div>
         </el-tooltip>
        </div>
       </li>
      </ul>
     </div>
     <div class="my_timeline_next" @click="moveRight">
      <img src="../../assets/arrow_right_blue.png" class="my_timeline_node"/>
      <div class="my_timeline_item_content" style="color: rgba(0,0,0,0);">下</div>
     </div>
    </div>
    <el-dialog :title="titleMessage" center :visible="mileStoUpdateVisible" width="50%"
          @open="onMileStoUpdateVisibleOpen()" @close="closeMileStone()">
     <stone-detail :projectId="this.projectId" :proNum="this.projectData.proNum" @closeMileStone="closeMileStone()" ref="stone-detail"
            @refreshMileStoneData="searchMileStone()"></stone-detail>
    </el-dialog>
   </div>
  </div>
</template>

<script>
  import API from '../../api/api_project';
  import StoneDetail from "../../components/project-info/stonedetail"
  import MemberDetail from "../../components/project-info/memberdetail.vue"
  export default {
    name: 'project-detail',
    components:{
      MemberDetail,
      StoneDetail,
    },
    data() {
      return {
        destroyIncomeStatistics:true,
        loading: false,
        titleMessage: '',
        mileStoUpdateVisible: false,
        my_timeline_item_line_last: "my_timeline_item_line_last",
        my_timeline_item_line_not_last: "my_timeline_item_line_not_last",

        menuTree:[],
        timeLineList: [],
        page:{
          total:0,
          pageNum: 0,
          pageSize: 10,
        },
        model: {
          select: "",
          searchConent: "",
          projectId: "",
          proName:"",
        },
        projectData:{
          proId: '',
          proNum: '',
          proName: '',
          hwDept: '',
          hwPo: '',
          busineMode: '1',
          buildProDate: '',
          startDate: '',
          expEndDate: '',
          hwPoDate: '',
          hwPoEndDate:'',
          realEndDate: '',
          proManageId:'',
          proQa:'',
          hwPm:'',
          proEstNum: '0',
          proState:'1'
        },
        proPeoId:'',
        projectId:'',
        proPeoUpdateVisible:false,
        projectMember: [],
      }
    },
    mounted(){
      this.projectId=this.$route.params.projectId

      this.searchMileStone()
      this.sortDataArray(this.timeLineList)
      //到数据库获取projectId对应的信息列表存入projectData
      API.getProjectInfo(this.projectId).then((data)=>{
        this.projectData=data.data;
        this.projectData.busineMode = this.projectData.busineMode.toString();
        this.projectData.proState = this.projectData.proState.toString();
      })
      this.search();
    },
    methods: {
      searchMileStone() {
        console.log('项目id:'+this.projectId)
        let params={
          proId:this.projectId,
        };
        API.getMileStoneList(params).then(data => {
          let result = data.data
          if (result && result.list) {
            if(this.timeLineList.length>0){
              this.timeLineList.splice(0,this.timeLineList.length);
            }
            for(var i=0;i<result.list.length;i++){
              this.timeLineList.splice(i, 1, result.list[i])
            }
            this.sortDataArray(this.timeLineList)
          }

        },({msg})=>{
          this.$message.error(msg);
        });
console.log('刷新里程碑列表')
console.log(this.timeLineList)
      },

      closeMileStone() {
        this.mileStoUpdateVisible = false;
        // this.projectId = '';
      },
      onMileStoUpdateVisibleOpen() {
        this.titleMessage = this.projectData.proNum + '项目里程碑';
        this.$nextTick(() => {
          let form = this.$refs["stone-detail"];
          form.initPage();
        });
      },
      changeActive(index) {
        this.timeIndex = index;
      },
      moveLeft() {
        let marginLeft = parseInt(this.$refs.mytimeline.style.marginLeft);
        let listNum = 0;

        if (Math.abs(marginLeft) > 10) {
          this.$refs.mytimeline.style.marginLeft = marginLeft + 120 + 'px';
        }
      },
      moveRight() {
        let marginLeft = parseInt(this.$refs.mytimeline.style.marginLeft);
        if (marginLeft <= 10 && (marginLeft >= -(this.timeLineList.length * 120))) {
          this.$refs.mytimeline.style.marginLeft = marginLeft - 120 + 'px';
        }
      },
//对数组根据日期进行排序
      sortDataArray(dataArray) {
        return dataArray.sort(function (a, b) {
          return Date.parse(a.endTime.replace(/-/g, "/")) - Date.parse(b.endTime.replace(/-/g, "/"));
        })
      },

      sortByKey(array,key){
        return array.sort(function(a,b){
          var y = a[key];
          var x = b[key];
          return((x<y)?-1:((x>y)?1:0));
        })

      },
      handleCurrentChange(val) {
        this.page.pageNum = val ;
        this.search();
      },
      handleSizeChange(val) {
        this.page.pageSize = val;
        this.search();
      },
      handleSearch(){
        this.page.pageNum= 0;
        this.search();
      },
      }
</script>

 .content {
  height: 100px;
 }

 .my_timeline_next {
  float: left;
  display: inline-block;
  background-color: #FCFCFC;
  cursor: pointer;
 }

 .my_timeline_prev {
  width: 50px;
  float: left;
   margin-top: 110px;
 }

 .my_timeline_next {
  width: 34px;
  margin-top: 80px;
 }

 .el-col-24 {
  margin-left: 10px;
  padding-bottom: 5px;
 }

 .el-col-12 {
  margin-left: 10px;
 }

 .tooltip {

 }

 .ul_box {
  width: 80%;
  height: 120px;
  display: inline-block;
  float: left;
  margin-top: 50px;
  overflow: hidden;
 }

 .my_timeline_item {
  display: inline-block;
  width: 150px;
 }

 .my_timeline_node {
  background-color: #FCFCFC;
  box-sizing: border-box;
  border-radius: 50%;
  cursor: pointer;
  width: 40px;
  height: 40px;
 }

 .node_picture {
  //margin-top: 20px;
  height: 25px;
  width: 25px;
  margin-left: 5px;
  margin-bottom: -7px;
 }

 .my_timeline_picture {
  margin-top: 13px;
  height: 25px;
  width: 25px;
 }

 .my_timeline_node.active {
  background-color: #fff !important;
  border: 6px solid #f68720;
 }

 .my_timeline_item_line_last {
  width: 100%;
  height: 10px;
  margin: -14px 0 0 28px;
  border-left: none;
 }

 .my_timeline_item_line_not_last {
  width: 100%;
  height: 10px;
  margin: -14px 0 0 25px;
  border-top: 2px solid #E4E7ED;
  border-left: none;
 }

 .my_timeline_item_content {
  margin: 10px 0 0 -10px;
  width: 90%; /*根据自己项目进行定义宽度*/
  font-size: 14px;
 }

 .detail_info {
  width: 80%;
  height: 250px;
  padding-bottom: 50px;
  overflow: hidden; /*设置超出的部分进行影藏*/
  text-overflow: ellipsis; /*设置超出部分使用省略号*/
  white-space: nowrap; /*设置为单行*/
  font-size: 14px;
 }
 .state_grade.process_wrap{
  border-color: #e4ebf0;
  margin-top: 150px;
  border-radius: 2px;
  padding-bottom: 10px;
 }

 .fall-back {
  float:right;
  margin-right: 20px;
  margin-bottom:50px;
 }
 .state_grade{
  border: 1px solid #e6e6e6;
  background: #FCFCFC;
  padding: 10px;
  //position: relative;
  /*height: 90px;*/
  height: 250px;
  margin-bottom: 15px;
  /*margin-top: 15px;*/
 }
 .title_top{
  height: 33px;
 }
 .obj_tit_wrap{
  border-bottom: 1px solid #e6e6e6;
  padding-bottom: 3px;
  font-size: 14px;
 }

 .obj_tit_mile{
   width: 150px;
   height: 35px;
 }

 .tit_deco{
  color: #9a9a9a;
  font-size: 14px;
 }
 .add_contain{
  display:inline-block;
  padding-bottom: 10px;
  padding-top: 20px;
 }
 .project_content_warp{
  background: #fdfdfd;
  margin-bottom: 15px;
 }
 .project_job_add{
  padding-left: 30px;
  background: #FCFCFC;
  border-bottom: 1px solid #E5E5E5;
  line-height: 10px;
  margin-bottom: 15px;
  font-size: 14px;
 }
 .project_info_span{
  display:inline-block;
  padding-left: 10px;
 }

 .el-col-8{
  height: 50px;
 }
</style>

编辑里程碑

stonedetail.vue

<template>

 <div>
  <el-row>
   <el-col :span="23">
    <div style="margin-top: 10px">
     <el-tag effect="dark" style="font-size: 16px;width: 110px;text-align: center">里程碑</el-tag>
    </div>
   </el-col>
   <el-col :span="1">
    <img src="../../assets/images/add.png" style="width: 30px;height: 30px;margin-top: 10px" @click="addItems()"/>
   </el-col>
  </el-row>
  <hr/>

  <el-row style="text-align: center">
   <el-col :span="3">
    <el-tag style="width: 100%;font-size: 14px">序 号</el-tag>
   </el-col>
   <el-col :span="8">
    <el-tag style="width: 100%;font-size: 14px">阶段名称</el-tag>
   </el-col>
   <el-col :span="7">
    <el-tag style="width: 100%;font-size: 14px">起始时间</el-tag>
   </el-col>
   <el-col :span="5">
    <el-tag style="width: 100%;font-size: 14px">结束时间</el-tag>
   </el-col>
  </el-row>

  <el-form label-width="100px" align="left" ref="form" style="text-align: left;" :model="model">
   <div v-for="(item, index) in model.timeLineList" :key="index">
    <el-row>
     <el-col :span="3">
      <input style="text-align: center" class="el-input__inner" type="text" v-model="index" disabled="true">
     </el-col>
     <el-col :span="8">
      <input placeholder="请输入阶段名称" style="text-align: center" class="el-input__inner" type="text"
          v-model="item.stageName">
     </el-col>
     <el-col :span="6">
      <el-date-picker
       style="width: 100%"
       type="date"
       :editable="false"
       v-model="item.startTime"
       placeholder="请选择起始时间"
       format="yyyy-MM-dd"
       value-format="yyyy-MM-dd"
      >
      </el-date-picker>

     </el-col>
     <el-col :span="6">
      <el-date-picker
       style="width: 100%"
       type="date"
       :editable="false"
       v-model="item.endTime"
       placeholder="请选择结束时间"
       format="yyyy-MM-dd"
       value-format="yyyy-MM-dd"
      >
      </el-date-picker>
     </el-col>
    </el-row>

    <el-row>
     <el-col :span="3">
      <input placeholder="阶段目标" style="text-align: center;" class="el-input__inner" type="text" disabled="true">
     </el-col>
     <el-col :span="20">
      <el-input v-model="item.stageTarget" placeholder="请输入阶段目标"></el-input>
      <!--     <textarea placeholder="请输入阶段目标" v-model="item.stageTarget" style="height: 30px;" class="el-input__inner" type="text"></textarea>-->
     </el-col>
    </el-row>

    <el-row>
     <el-col :span="3">
      <input placeholder="验收标准" style="text-align: center;" class="el-input__inner" type="text" disabled="true">
     </el-col>
     <el-col :span="20">
      <el-input v-model="item.acceptStar" placeholder="请输入验收标准"></el-input>
     </el-col>
    </el-row>

    <el-row>
     <el-col :span="3">
      <input placeholder="里程碑状态" style="text-align: center;" class="el-input__inner" type="text" disabled="true">
     </el-col>
     <el-col :span="20">
      <template>
       <el-select v-model="item.milepostState" placeholder="请选择">
        <el-option
         v-for="item in milepostStateList"
         :key="item.ref_id"
         :label="item.ref_value"
         :value="item.ref_id">
        </el-option>
       </el-select>
      </template>
     </el-col>

     <el-col :span="1">
      <img src="../../assets/images/delete.png" style="width: 30px;height: 30px" @click="deleteItems(index)"/>
     </el-col>
    </el-row>
   </div>
  </el-form>
  <div style="text-align: center;margin-top: 30px">
   <el-button type="primary" @click="submit()">确认修改</el-button>
  </div>
 </div>


</template>

<script>
  import API from '../../api/api_project';

  export default {
    name: "stoneDetail",
    props: ['projectId', 'proNum'],
    watch: {
      'proId': {
        // projectId,所以每次都能监听到变化
        immediate: true,
        handler: function (val) {
          if (!val) return;
          this.onProjectIdChange(val);
        }
      }
    },
    data() {
      return {
        proId:'',
        milepostStateList: [{
          ref_id: "1",
          ref_value: '打开',
          ref_key: '1'
        }, {
          ref_id: "2",
          ref_value: '超期',
          ref_key: '2'
        }, {
          ref_id: "3",
          ref_value: '关闭',
          ref_key: '3'
        }],
        deleteList: [],
        model: {
          timeLineList: [],
        },

      }
    },
    methods: {
      /**
       * 提交修改的信息
       */
      submit: function () {
        this.$refs.form.validate((valid) => {
          if (!valid) {
            this.$message.error('请填写正确信息');
            return;
          }


          console.log('编辑里程碑结果:')
          console.log(this.model.timeLineList)

          let proMileposts = this.model.timeLineList

          API.updatetMileStone(proMileposts).then(data => {
            if (data.code == 200) {
              this.$message.success("修改成功");
              this.refreshMileStoneData();
              this.close();
            } else {
              this.$message.error(data.msg);
              // this.close();
            }
          })


        });
      },
      close() {
        this.$emit("closeMileStone");
        this.proId=''
        this.model.timeLineList.splice(0,this.model.timeLineList.length)
      },
      refreshMileStoneData() {
        this.$emit("refreshMileStoneData");

      },
      addItems() {
        this.model.timeLineList.push({
          milepostId:'',
          proId: this.proId,
          stageName: '',
          startTime: this.addDate(),
          endTime: this.addDate(),
          stageTarget: '',
          acceptStar: '',
          deliverableName: '',
          milepostState: '1',
        });

      },
      addDate() {
        var date = new Date();
        var seperator1 = "-";
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var strDate = date.getDate();
        if (month >= 1 && month <= 9) {
          month = "0" + month;
        }
        if (strDate >= 0 && strDate <= 9) {
          strDate = "0" + strDate;
        }
        var currentdate = year + seperator1 + month + seperator1 + strDate;
        return currentdate;
      },
      deleteItems(index) {
        this.$confirm('确认删除该记录吗?', '提示', {
          confirmButtonClass: 'el-button--warning'
        }).then(() => {
          if(this.model.timeLineList[index].milepostId)
          {
            API.deleteMileStone(this.model.timeLineList[index].milepostId).then(data=>{
              if(data.code===200)
              {
                this.$message.success("删除成功");
                this.model.timeLineList.splice(index, 1);
                this.refreshMileStoneData();
              }else {
                this.$message.error(data.msg);
              }
            })
          }
          else{
            this.model.timeLineList.splice(index, 1);
          }

        }).catch(() => {});


      },
      onProjectIdChange(id) {
        this.model.timeLineList.splice(0,this.model.timeLineList.length)
        // if (id) {
          let params={
            proId:id,
          };
          API.getMileStoneList(params).then(data => {
            let result = data.data
            if (result && result.list) {
              for(var i=0;i<result.list.length;i++){
                this.model.timeLineList.splice(i, 1, result.list[i])
              }
            }
          }, ({msg}) => {
            this.$message.error(msg);
          });
        // }
        console.log('dailog打开里程碑列表')
        console.log(this.model.timeLineList)
      },
      initPage() {
         this.proId=this.projectId;
        if (this.proId) {
          this.onProjectIdChange(this.proId);
        }

      }
    },
  }
</script>

<style scoped>

</style>

以上这篇Vue时间轴 vue-light-timeline的用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS继承--原型链继承和类式继承
Apr 08 Javascript
js中的布尔运算符使用介绍
Nov 20 Javascript
JS获取URL中的参数数据
Dec 05 Javascript
jquery遍历select元素(实例讲解)
Dec 31 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
Aug 01 Javascript
jQuery多级联动下拉插件chained用法示例
Aug 20 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
Feb 24 Javascript
JS库之wow.js使用方法
Sep 14 Javascript
JavaScript设计模式之职责链模式应用示例
Aug 07 Javascript
js时间转换毫秒的实例代码
Aug 21 Javascript
JavaScript实现网页留言板功能
Nov 23 Javascript
小程序实现列表倒计时功能
Jan 29 Javascript
antd日期选择器禁止选择当天之前的时间操作
Oct 29 #Javascript
vue制作toast组件npm包示例代码
Oct 29 #Javascript
antd-日历组件,前后禁止选择,只能选中间一部分的实例
Oct 29 #Javascript
解决antd日期选择组件,添加value就无法点击下一年和下一月问题
Oct 29 #Javascript
浅析微信小程序自定义日历组件及flex布局最后一行对齐问题
Oct 29 #Javascript
解决ant Design中Select设置initialValue时的大坑
Oct 29 #Javascript
解决Ant Design Modal内嵌Form表单initialValue值不动态更新问题
Oct 29 #Javascript
You might like
php上传、管理照片示例
2006/10/09 PHP
应用开发中涉及到的css和php笔记分享
2011/08/02 PHP
浅谈关于PHP解决图片无损压缩的问题
2017/09/01 PHP
php+redis实现商城秒杀功能
2020/11/19 PHP
PHP开发api接口安全验证操作实例详解
2020/03/26 PHP
jQuery 判断页面元素是否存在的代码
2009/08/14 Javascript
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
javascript下4个跨浏览器必备的函数
2010/03/07 Javascript
23个Javascript弹出窗口特效整理
2011/02/25 Javascript
js中return false(阻止)的用法
2013/08/14 Javascript
纯js简单日历实现代码
2013/10/05 Javascript
jQuery实现瀑布流的取巧做法分享
2015/01/12 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
Angular1.x复杂指令实例详解
2017/03/01 Javascript
利用pm2部署多个node.js项目的配置教程
2017/10/22 Javascript
Vue 中使用vue2-highcharts实现曲线数据展示的方法
2018/03/05 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
基于vue-router 多级路由redirect 重定向的问题
2018/09/03 Javascript
Vuex 使用 v-model 配合 state的方法
2018/11/13 Javascript
iview实现图片上传功能
2020/06/29 Javascript
python自动化测试之从命令行运行测试用例with verbosity
2014/09/28 Python
Python GUI Tkinter简单实现个性签名设计
2018/06/19 Python
元组列表字典(莫烦python基础)
2019/04/03 Python
Python flask框架实现浏览器点击自定义跳转页面
2020/06/04 Python
Python-opencv实现红绿两色识别操作
2020/06/04 Python
如何使用python记录室友的抖音在线时间
2020/06/29 Python
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
小学教育毕业生自荐信
2013/11/18 职场文书
技能竞赛活动方案
2014/02/21 职场文书
竞聘上岗演讲
2014/05/19 职场文书
2014年保洁工作总结
2014/11/24 职场文书
写给纪委的违纪检讨书
2015/05/05 职场文书
TypeScript 使用 Tuple Union 声明函数重载
2022/04/07 Javascript
MySql分区类型及创建分区的方法
2022/04/13 MySQL
详解Spring Bean的配置方式与实例化
2022/06/10 Java/Android
win11自动弹出虚拟键盘怎么关闭? Win11关闭虚拟键盘的技巧
2023/01/09 数码科技