Vue+Element实训:后台管理系统

Vue+Element实训:后台管理系统-3

续后台管理系统–2

首页创建

  • 首先我们的首页是一个左右布局 所以来到elementuiplus官网中来进行布局设置
    • 找到布局容器并且找到对应效果
    • 注入到首页页面中
  • 设置背景颜色区分区块
  • 实现高度自适应

elementui-plus–Menu导航

  • 在homeview文件夹下创建components文件夹并且创建文件用来容纳左侧导航
    • 创建首页左侧导航
  • 在首页中引用使用

导航折叠的菜单

  • 创建左侧顶部菜单组件
  • 在首页中引用使用
  • 在头部组件中设置点击图标用来切换导航 并设置图标样式
  • 在vuex中创建模块 用来设置点击图标后切换导航的布尔值
    • 在store下新建module文件夹用来容纳首页的vuex模块
  • 在vuex的index文件中引用使用模块
  • 给图标设置点击事件 从而修改vuex的布尔值 在真假中切换

Vuex–useStore

  • 引用useStore 并且调用commit来进行数据的修改
  • 创建对应的mutations
  • 在页面中添加相反的箭头 用v-ifvuex的数据具体显示哪一个
  • 在左侧导航设置 collapse属性控制导航折叠
  • 导航是变了,但是右侧整体宽度不会随着页面的改变而变化,把左侧的宽度设置成auto即可自动改变

首页多级路由设置

首页下有:

  • 数据统计 EchartsView.vue

  • 住户信息统计 UserOne.vue

    • 住户信息展示 UserList.vue
    • 住户信息修改 UserUpdate.vue
      创建对应页面 与路由规则的配置
  • 设置路由出口

    • 在homeview页面下右侧下方区域设置router-view路由出口 并且在userone.vue中设置路由出口
    • 在页面中进行测试

路由实时路由获取

  • 我们左侧的导航是根据路由规则实时获取动态展示 所以先把当前路由规则读取出来
    • 在左侧导航
      • 在leftnav.vue中获取当前路由信息
    • 设置路由标题与分类标题(因为有可能有二级菜单)
      • 修改左侧列表删除掉没有用的内容
import { createRouter, createWebHistory,createWebHashHistory, RouteRecordRaw } from 'vue-router'
import {
  MessageBox,Grid,User
} from '@element-plus/icons-vue'

const routes: Array<RouteRecordRaw> = [
  
  {
    path: '/login',
    name: 'login',
    
    component: () => import( '../views/login/LoginView.vue')
  },
   
  {
    path: '/home',
    name: 'home',
    
    component: () => import( '../views/home/HomeView.vue'),
    children:[
      {
        path:"/echarts",
        name:"echarts",
        component:()=>import("../views/home/childrens/EchartsView.vue"),
        meta:{
          title:"数据展示",
          icon:MessageBox
        }
      },
      // {
      //   path:"/pay",
      //   name:"pay",
      //   component:()=>import("../views/home/childrens/PayList.vue"),
      //   meta:{
      //     title:"缴费管理",
      //     icon:Grid
      //   }

      // },
      {
        path:"/user",
        name:"user",
        component:()=>import("../views/home/childrens/UserOne.vue"),
        meta:{
          title:"住户信息",
          icon:User
        },
        children:[
          {
            path:"/userList",
            name:"userList",
            component:()=>import("../views/home/childrens/UserList.vue"),
            meta:{
              classifyTitle:"住户信息",
              title:"住户信息列表"
            }
          },
          {
          path:"/userupdata",
            name:"userupdata",
            component:()=>import("../views/home/childrens/UserUpdata.vue"),
            meta:{
              classifyTitle:"住户信息",
              title:"住户信息修改"
            }
          },
        ]
      },
    ]
  },
  {
    path:"/",
    redirect:"/login"
  }
]

const router = createRouter({
  history: createWebHashHistory(process.env.BASE_URL),
  routes
})

export default router
  • 开始遍历之前得到的路由信息
  • 添加 展示数据
  • 生成二级菜单
  • 设置导航
    • 在导航中也设置index属性的值为path路径从而完成页面的跳转
    • 宽度有问题设置下宽度

住户信息列表

  • 获取到elementplus的表格到我们页面当中Userlist.vue
  • 增加点数据之后发现数据会把页面撑大 所以我们要进行分页处理
  • 设置分页 找到带附加功能的分页 并且使用All combined这个分页项
  • 设置分页属性与方法
  • 修改绑定的参数
  • 修改表格宽度
    • 删除掉表格上面的width属性

住户信息列表查找

  • 在表格顶部添加输入框(elementui 表格想相关设置) 并且使用计算属性处理数据

住户信息修改

  • 复用用户信息列表userlist组件内容到userupdate组件中
  • 添加删除和修改的按钮从element找
  • 设置点击修改之后的输入弹框
  • 在elementplus中的对话框 dialog中找到自定义内容
  • 设置嵌套表单的弹出框
  • 在components中新建 组件用来封装弹出框 UpdateDialog.vue
  • 把封装的组件在userupdate中引用 使用
  • 分析代码 发现当点击之后需要设置一个变量的改变控制弹出框 但是不同组件 所以使用vuex来进行这个变量的状态共享
    • vuex中创建state
    • 在页面的修改按钮上绑定事件点击之后修改这个状态
    • 创建mutations
    • 在弹出框上绑定变量状态
  • 在修改弹出框的两个按钮 点击之后关闭弹出框
  • 修改弹出框样式(内容)
  • 修改每隔elform-item上的label-wath属性到 el-from上
  • 修改输入框宽度
  • 开始修改
    • 当点击确定按钮时候调用函数并且在函数中得到修改的输入框的值
      • 修改输入框的类型 和绑定的变量
    • 在函数中得到输入框的值
    • 但是这个方法确定和取消都在用 所以我们传递一个形参 来辨别用户到底点击了那个
      • 设置表格数据在vuex中
      • 因为我们要对展示数据进行操纵 所以把原有写在组件中的表格数据放到vuex中
      • 把表格的数据从vuex中获取

项目分辨率响应式创建

  • 我们的项目是需要根据页面的大小改变 做出响应式改变的 所以我们可以使用
  • 我们可以使用 第三方插件flexible.js帮助我们修改html根节点的font-size大小 从而控制当前页面的rem**(会根据页面的html根节点font-size大小改变而改变)**样式改变
  • flexible.js
    • flexible.js web自适应方案 阿里团队开源的一个库。使用flexible.js轻松搞定各种不同的移动端设备兼容自适应问题。
      • 下载 npm i -S lib-flexible
      • 在main.js中进行配置
    • 修改flexible配置
      • 因为默认情况下只会在540px分辨率一下生效 所以我们需要根据我们的项目分辨率进行调整
  • 这个时候重启项目大家打开浏览器调试器 即可发现在浏览器大小改变的时候 在html根节点上会自动设置一个font-size
  • cssrem插件 :我们在写代码的时候发现如果我们都根据80px为1rem在编写代码的时候转换非常的麻烦 所以我们可以在vscode中安装一个cssrem的插件帮助我们进行转换 这样一来开发过程中会更加的方便
    • 在vscode扩展中找到 cssrem插件 最新名字叫px to rem & rpx 安装到vscode中 点击右下角设置
    • 修改Root Font Size(基准font-size) 配置项为80即可

数据展示组件封装

  • 创建一个大容器来容纳左右两个区域
  • 在EchartsView.vue页面中创建一个大容器
    • 创建容器样式
    • 设置左右布局容器
    • 设置左右布局样式
    • 左右图表展示区块容器样式
  • 要展示的2个区域的容器效果是一样的。所以我们可以剥离成一个组件 然后重复调用即可。并且在其中放置slot槽口 后期方便向容器内插入图表
    • 创建容器组件
    • 在components文件夹下创建 ItemPage.vue
    • 编写样式与插槽
  • 在views下的Echartview.vue中引用调用使用
  • 运行之后大家会发现左右区块就展现出2个容器
  • 左右每个区块内容插入容器槽口
    • 一共2个图表 使用一个公共的组件容器 所以我们编写这2个不同图表的组件并且 分别显示
    • 创建2个组件 在components下 isOne.vue等等 一共2个
    • 然后在2个文件中分别设置相关内容与样式(每个图表的标题不一样要修改)
    • 在EchartsView.vue中引用调用使用这4个组件 并且插入对应的槽口

代码部分

-EchartsView.vue

<template>
    <div class="container">
    <div class="itemleft">
        <Ip>
            <template #main>
               <One/>
            </template>
        </Ip>
    </div>
    <div class="itemright">
        <Ip>
            <template #main>
               <Two/>
            </template>
        </Ip>
    </div>
    </div>
</template>

<script setup>
import Ip from "../../../components/ItemPage.vue"
import One from "../../../components/IsOne.vue"
import Two from "../../../components/IsTwo.vue"
</script>

<style lang="scss">
.container{
    width:100%;
    margin:0 auto;
    background-color: gray;
    display: flex;
    .itemleft,.itemright{
        flex:1;
    }
}
</style>
  • UserList.vue
<template>
    <el-table :data="tableData.listdata.slice((currentPage4-1)*pageSize4,currentPage4*pageSize4)" stripe style="width: 100%">
    <el-table-column prop="id" label="编号"  />
    <el-table-column prop="title" label="楼盘"/>
    <el-table-column prop="type" label="类型" />
    <el-table-column prop="num" label="门牌号" />
    <el-table-column prop="hometype" label="户型" />
    <el-table-column prop="name" label="户主" />
    <el-table-column>
        <template #header>
            <el-input v-model="search" size="small" placeholder="请输入查询内容" @blur="searchLink"/>
        </template>
    </el-table-column>
  </el-table>
  <!-- 分页 -->
  <el-pagination
      v-model:current-page="currentPage4"
      v-model:page-size="pageSize4"
      :background="background"
      layout="total, sizes, prev, pager, next, jumper"
      :current_page="currentPage4"
      :total="tableData.listdata.length"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
</template>

<script lang="ts" setup>
import { Search } from '@element-plus/icons-vue/dist/types';
import { ref,onMounted,reactive } from 'vue'
import link from "../../../api/Link.js"
import apiUrl from "../../../api/Url.js"

let search=ref("")
const currentPage4 = ref(1)

const pageSize4 = ref(15)
const small = ref(false)
const background = ref(false)
const disabled = ref(false)

const handleSizeChange = (val: number) => {
  pageSize4.value=val
}
const handleCurrentChange = (val: number) => {
   currentPage4.value=val
}

let tableData=reactive({
    listdata:[]
})
let searchLink=()=>{
    link(apiUrl.userList,"get",{},{name:search.value}).then((ok:any)=>{
        console.log(ok)
        tableData.listdata=ok.data
    })
}

onMounted(()=>{
    link(apiUrl.userList).then((ok:any)=>{
        console.log(ok)
        tableData.listdata=ok.data
    })

})
</script>

<style>
  • UserOne.vue
<template>
    <div>
       
        <router-view/>
    </div>
</template>

<script>

</script>

<style>

</style>
  • UserUpdata.vue
<template>
    <el-table :data="
    $store.state.HomeModule.listdata.slice((currentPage4-1)*pageSize4,currentPage4*pageSize4)" stripe style="width: 100%">
    <el-table-column prop="id" label="编号"  />
    <el-table-column prop="title" label="楼盘"/>
    <el-table-column prop="type" label="类型" />
    <el-table-column prop="num" label="门牌号" />
    <el-table-column prop="hometype" label="户型" />
    <el-table-column prop="name" label="户主" />
    <el-table-column>

        <el-table-column label="操作">
      <template #default="scope">
        <el-button size="small" @click="handleEdit(scope.$index, scope.row)"
          >修改</el-button
        >
        <el-button
          size="small"
          type="danger"
          @click="handleDelete(scope.$index, scope.row)"
          >删除</el-button
        >
      </template>
    </el-table-column>
        
    </el-table-column>
  </el-table>
  <!-- 分页 -->
  <el-pagination
      v-model:current-page="currentPage4"
      v-model:page-size="pageSize4"
      :background="background"
      layout="total, sizes, prev, pager, next, jumper"
      :current_page="currentPage4"
      :total="tableData.listdata.length"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />

    <!-- 修改的弹出框 -->
    <Ud/>

</template>

<script lang="ts" setup>
import { Search } from '@element-plus/icons-vue/dist/types';
import { ref,onMounted,reactive } from 'vue'
import link from "../../../api/Link.js"
import apiUrl from "../../../api/Url.js"
import Ud from '../../../components/UpdataDialog.vue';
import {useStore} from "vuex"
let store=useStore()

interface User {
  date: string
  name: string
  address: string
}

let search=ref("")
const currentPage4 = ref(1)

const pageSize4 = ref(15)
const small = ref(false)
const background = ref(false)
const disabled = ref(false)

const handleSizeChange = (val: number) => {
  pageSize4.value=val
}
const handleCurrentChange = (val: number) => {
   currentPage4.value=val
}

const handleEdit = (index: number, row: User) => {
  console.log(index, row);
  store.commit("SET_DIALOG",row)
}
const handleDelete = (index: number, row: User) => {
  console.log(index, row);
  store.dispatch("DEL_DATA",row)
}

let tableData=reactive({
    listdata:[]
})



onMounted(()=>{

    store.dispatch("USERUPDATA_LIST")

    link(apiUrl.userList).then((ok:any)=>{
        console.log(ok)
        tableData.listdata=ok.data
    })

})
</script>

<style>

</style>
  • HomeView.vue
<template>
   <div class="common-layout">
    <el-container>
      <el-aside width="auto">
        <Lm/>
      </el-aside>
      <el-container>
        <el-header>
            <Rm/>
        </el-header>
        <el-main>
          <router-view/>
        </el-main>
      </el-container>
    </el-container>
  </div>

</template>

<script setup>
import Lm from "../../components/LeftMenu.vue"
import Rm from "../../components/RightTop.vue"
</script>

<style lang="scss">
    .el-aside{
        background-color: #545c64;
    }
    .el-header{
        background-color: white;
    }
    .el-main{
        background-color: gainsboro;
    }
    .el-aside,.el-container,.common-layout,#app,body,html{
        height:100%;
    }
</style>
  • IsOne.vue
<template>
    <div>
        <h2>人数统计</h2>
        <div id="chartone" class="one"></div>
    </div>
</template>

<script setup>
import {inject,onMounted,reactive} from "vue"
import link from "../api/Link.js"
import url from "../api/Url.js"
let $echarts=inject("echarts")

let data=reactive({})
let xdata=reactive([])
let ydata=reactive([])

onMounted(()=>{
    
    let myChart=$echarts.init(document.getElementById("chartone"))

    
    link(url.chartDataOne).then((ok)=>{
        let {data}=ok;
        console.log(data)

        xdata=data.map(v=>v.title)
        ydata=data.map(v=>v.num)

        console.log("x",xdata)
        console.log("y",ydata)

        myChart.setOption({
        xAxis:{
            type:"value",
            axisLine:{
                lineStyle:{
                    color:"#fff"
                }
            }
        },
        yAxis:{
            type:"category",
            data:xdata,
            axisLine:{
                lineStyle:{
                    color:"#fff"
                }
            }
        },
        grid:{
            top:"3%",
            left:"1%",
            bottom:"3%",
            right:"6%",
            containLabel:true
        },
        series:[
            {
                type:"bar",
                data:ydata,
                itemStyle:{
                    normal:{
                        barBorderRadius:[0,20,20,0],
                        color:new $echarts.graphic.LinearGradient(0,0,1,0,[
                            {
                                offset:0,
                                color:"#005eaa"
                            },
                            {
                                offset:0.5,
                                color:"#339ca7"
                            },
                            {
                                offset:1,
                                color:"#cda818"
                            }
                        ])
                    }
                }
            }
        ]
    })
    })

   
})
</script>

<style lang="scss" scoped>
   h2{
    height: 0.6rem;
    color:#fff;
    text-align: center;
    font-size: 0.25rem;
   }
   .one{
    height:4.5rem;
   }
</style>
  • IsTwo.vue
<template>
    <div>
        <h2>报修统计</h2>
        <div id="charttwo" class="two"></div>
    </div>
</template>

<script setup>
import {inject,onMounted,reactive} from "vue"
import link from "../api/Link.js"
import url from "../api/Url.js"
let $echarts=inject("echarts")

// let data=reactive({})
let xdata=reactive([])
let ydata=reactive([])

onMounted(()=>{
    
    let myChart=$echarts.init(document.getElementById("charttwo"))

    
    link(url.chartDataTwo).then((ok)=>{
        console.log(ok)
        myChart.setOption({
            legend:{top:"bottom"},
            tooltip:{},
            series:[
             {
                type:"pie",
              data:ok.data,
              radius:[10,100],
              center:["50%","45%"],
              roseType:"area"
             }
            ]
        })
    })
})
</script>

<style lang="scss" scoped>
   h2{
    height: 0.6rem;
    color:#fff;
    text-align: center;
    font-size: 0.25rem;
   }
   .one{
    height:4.5rem;
   }
   .two{
    height:4.5rem;
   }
</style>
  • ItemPage.vue
<template>
<div class="item">
    <slot name="main"></slot>
</div>
</template>

<script setup> 

</script>

<style lang="scss">
.item{
    height:5.125rem;
    border:1px solid grey;
    margin:0.25rem;
    background-color: gainsboro;
}
</style>
  • LeftMenu.vue
<template>
<div class="item">
    <slot name="main"></slot>
</div>
</template>

<script setup> 

</script>

<style lang="scss">
.item{
    height:5.125rem;
    border:1px solid grey;
    margin:0.25rem;
    background-color: gainsboro;
}
</style>
  • RightTop.vue
<template>
   <div>
    <el-icon @click="ck"><ArrowRightBold v-if="$store.state.HomeModule.navBool"/><ArrowLeftBold v-else/></el-icon>
   </div> 
</template>
 
<script setup>
import {ArrowRightBold,ArrowLeftBold} from '@element-plus/icons-vue'
// import {ref}from "vue"
// let bool=ref(true)
// let ck=()=>{
//     bool.value=!bool.value;
//     console.log("我被点击了")
// }
import {useStore}from "vuex"
let store=useStore()
let ck=()=>{
    store.commit("SET_NAV_BOOL")
}
</script>

<style lang="scss">
   .el-header{
    line-height: 65px;
    .el-icon{
        font-size: 20px;
    }
   }
</style>
  • UpdataDialog.vue
<template>

  
    <el-dialog v-model="$store.state.HomeModule.dialogFormVisible" title="请输入修改信息">
      <el-form :model="form" :label-width="formLabelWidth">
        <el-form-item label="户主" :label-width="formLabelWidth">
          <el-input v-model="form.name" autocomplete="off" />
        </el-form-item>
        <el-form-item label="楼盘名称" :label-width="formLabelWidth">
          <el-input v-model="form.title" autocomplete="off" />
        </el-form-item>
        <el-form-item label="房源类型" :label-width="formLabelWidth">
          <el-input v-model="form.type" autocomplete="off" />
        </el-form-item>
        <el-form-item label="门牌号" :label-width="formLabelWidth">
          <el-input v-model="form.num" autocomplete="off" />
        </el-form-item>
        <el-form-item label="房源户型" :label-width="formLabelWidth">
          <el-input v-model="form.hometype" autocomplete="off" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeDialog(0)">取消</el-button>
          <el-button type="primary" @click="closeDialog(1)">
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </template>
  
  <script lang="ts" setup>
  import { composeEventHandlers } from 'element-plus/es/utils';
import { reactive, ref } from 'vue'
  import { useStore } from "vuex"
  import  link from "../api/Link.js"
  import url from "../api/Url.js"

  let store=useStore()
//   const dialogFormVisible = ref(false)
  const formLabelWidth = '140px'
  
  const form = reactive({
    name: '',
    title:"",
    type:"",
    num:"",
    hometype:""
  })

  let closeDialog=(num:number)=>{
    
    store.commit("DIALOG")
    if(num==1){
        console.log(store.state.HomeModule.uplistData)

        let data={
            name:form.name,title:form.title,type:form.type,num:form.num,hometype:form.hometype
        }

        link(url.userList+"/"+store.state.HomeModule.uplistData.id,"PUT",data).then((ok:any)=>{
            console.log(ok)
        })
    }
  }
  </script>
  <style scoped>
  .el-button--text {
    margin-right: 15px;
  }
  .el-select {
    width: 300px;
  }
  /* .el-input {
    width: 300px;
  } */
  .dialog-footer button:first-child {
    margin-right: 10px;
  }
  </style>
  • HomeModule.ts
import link from "../../api/Link.js"
import apiUrl from "../../api/Url.js"
const HomeModule: object={
    state:{
        navBool: true,
        dialogFormVisible:false,
        uplistData:{},
        listdata:[]
    },
    mutations:{
        SET_NAV_BOOL(state:any){
            state.navBool=!state.navBool
        },
        SET_DIALOG(state:any,paylog:any){
            state.dialogFormVisible=!state.dialogFormVisible;

            state.uplistData=paylog

        },
        DIALOG(state:any){
            state.dialogFormVisible=!state.dialogFormVisible;
            window.location.reload()

        },
        LISTDATA(state:any,paylog:any){
            state.listdata=paylog
        },
    },
    actions:{
        USERUPDATA_LIST(context:any){
            link(apiUrl.userList).then((ok:any)=>{
                console.log(ok)

                context.commit("LISTDATA",ok.data)
               
            })
        },
        DEL_DATA(context:any,payload:any){
            link(apiUrl.userList+"/"+payload.id,"delete").then((ok:any)=>{
               console.log(ok)
               window.location.reload()
               
            })

        }
    }


}

export default HomeModule
  • Url.js
let apiUrl={
    register: "/register",
    userList:"/userlist",
    chartDataOne:"/chartDataOne",
    chartDataTwo:"/chartDataTwo"
}

export default apiUrl
  • data.json
{
  "register": [
    {
      "id": 1,
      "name": "123@123.com",
      "pwd": "admin123"
    },
    {
      "name": "982852662@qq.com",
      "pwd": "lyqlyq010502",
      "id": 2
    },
    {
      "name": "999@qq.com",
      "pwd": "admin123",
      "id": 3
    },
    {
      "name": "777@123.com",
      "pwd": "admin123",
      "id": 4
    },
    {
      "name": "999@qq.com",
      "pwd": "123123lyq",
      "id": 5
    },
    {
      "name": "999@123.com",
      "pwd": "aba0182ef03fdc7b7116729df2a6ec66",
      "id": 6
    },
    {
      "name": "111@123.com",
      "pwd": "0192023a7bbd73250516f069df18b500",
      "id": 7
    },
    {
      "name": "101010@qq.com",
      "pwd": "2cca4024094f1a971841a765b0b73941",
      "id": 8
    },
    {
      "name": "10101010@qq.com",
      "pwd": "0b11a1d4619ede26f88d683343a6fd51",
      "id": 9
    },
    {
      "name": "111111@qq.com",
      "pwd": "4e91b273dad767d777d41e62d341ffc1",
      "id": 10
    }
  ],
  "userList": [
    {
      "id": 287,
      "title": "海天家园",
      "type": "商铺",
      "num": "2-2-2",
      "hometype": "三室一厅",
      "name": "王五"
    },
    {
      "id": 381,
      "title": "海天家园",
      "type": "住宅",
      "num": "3-1-2",
      "hometype": "一室一厅",
      "name": "李四"
    },
    {
      "id": 382,
      "title": "海天家园",
      "type": "住宅",
      "num": "3-2-2",
      "hometype": "三室一厅",
      "name": "黄潘"
    },
    {
      "id": 397,
      "title": "海天家园",
      "type": "住宅",
      "num": "3-3-2",
      "hometype": "三室两厅",
      "name": "王耀"
    },
    {
      "id": 393,
      "title": "海天家园",
      "type": "住宅",
      "num": "4-2-2",
      "hometype": "三室三厅",
      "name": "周七"
    },
    {
      "id": 317,
      "title": "海天家园",
      "type": "商铺",
      "num": "5-1-2",
      "hometype": "三室两厅",
      "name": "陈凡"
    },
    {
      "id": 487,
      "title": "海天家园",
      "type": "住宅",
      "num": "5-2-2",
      "hometype": "三室一厅",
      "name": "陈章"
    },
    {
      "id": 380,
      "title": "海天家园",
      "type": "住宅",
      "num": "1-2-2",
      "hometype": "三室两厅",
      "name": "林二"
    },
    {
      "id": 1187,
      "title": "海天家园",
      "type": "商铺",
      "num": "12-1-2",
      "hometype": "两室两厅",
      "name": "张武"
    },
    {
      "id": 1287,
      "title": "海天家园",
      "type": "商铺",
      "num": "21-2-2",
      "hometype": "三室一厅",
      "name": "王五"
    },
    {
      "id": 1381,
      "title": "海天家园",
      "type": "住宅",
      "num": "32-1-2",
      "hometype": "一室一厅",
      "name": "李四"
    },
    {
      "id": 1382,
      "title": "海天家园",
      "type": "住宅",
      "num": "13-2-2",
      "hometype": "三室一厅",
      "name": "黄三"
    },
    {
      "id": 1397,
      "title": "海天家园",
      "type": "住宅",
      "num": "13-3-2",
      "hometype": "三室两厅",
      "name": "王土"
    },
    {
      "id": 3193,
      "title": "海天家园",
      "type": "住宅",
      "num": "40-2-2",
      "hometype": "三室三厅",
      "name": "周伦"
    },
    {
      "id": 3217,
      "title": "海天家园",
      "type": "商铺",
      "num": "9-1-2",
      "hometype": "三室两厅",
      "name": "陈军"
    },
    {
      "id": 1487,
      "title": "海天家园",
      "type": "住宅",
      "num": "8-2-2",
      "hometype": "三室一厅",
      "name": "陈章"
    },
    {
      "id": 2387,
      "title": "海天家园",
      "type": "住宅",
      "num": "7-3-2",
      "hometype": "三室两厅",
      "name": "林北"
    },
    {
      "id": 2187,
      "title": "海天家园",
      "type": "商铺",
      "num": "9-8-2",
      "hometype": "两室两厅",
      "name": "张明"
    },
    {
      "id": 2287,
      "title": "海天家园",
      "type": "商铺",
      "num": "3-7-2",
      "hometype": "三室一厅",
      "name": "王三"
    },
    {
      "id": 1381,
      "title": "海天家园",
      "type": "住宅",
      "num": "4-2-2",
      "hometype": "一室一厅",
      "name": "李四"
    },
    {
      "id": 3282,
      "title": "海天家园",
      "type": "住宅",
      "num": "13-2-2",
      "hometype": "三室一厅",
      "name": "张涛"
    },
    {
      "id": 3927,
      "title": "海天家园",
      "type": "住宅",
      "num": "32-3-2",
      "hometype": "三室两厅",
      "name": "王耀"
    },
    {
      "id": 3932,
      "title": "海天家园",
      "type": "住宅",
      "num": "41-2-2",
      "hometype": "三室三厅",
      "name": "周鳞"
    },
    {
      "id": 2317,
      "title": "海天家园",
      "type": "商铺",
      "num": "10-2-2",
      "hometype": "三室两厅",
      "name": "陈静"
    },
    {
      "id": 2487,
      "title": "海天家园",
      "type": "住宅",
      "num": "14-5-2",
      "hometype": "三室一厅",
      "name": "陈航"
    }
  ],
  "chartDataOne":[
    {"title":"一号楼","num":1827},
    {"title":"二号楼","num":342},
    {"title":"三号楼","num":541},
    {"title":"四号楼","num":1347},
    {"title":"五号楼","num":2431},
    {"title":"六号楼","num":876},
    {"title":"七号楼","num":1578}
],
"chartDataTwo":[
  { "value": 567, "name":"卫生" },
  { "value": 123, "name":"电梯" },
  { "value": 324, "name":"停车引导" },
  { "value": 89, "name":"水电" },
  { "value": 453, "name":"一般报修" },
  { "value": 767, "name":"门禁" }
]
}

实现效果

数据展示页面
住户信息列表
住户信息修改页面
修改住户信息
修改成功
实现侧栏伸缩

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Vue Element UI 后台管理系统首页模板是一个基于Vue.jsElement UI开发的后台管理系统的首页模板。它提供了丰富的UI组件和功能,帮助开发人员快速搭建和定制自己的后台管理系统。 该模板的特点是简洁、美观、易于使用。它采用响应式设计,可以适应不同尺寸的屏幕,包括电脑、平板和手机。页面布局清晰,组件排列合理,用户可以直观地了解系统的各个功能模块和数据统计信息。 该模板提供了丰富的UI组件,包括按钮、表格、表单、对话框、菜单等。这些组件可以轻松地与后端数据进行绑定,实现数据的展示和交互。同时,该模板还提供了许多常用的功能组件,如权限管理、数据可视化、文件上传等,使得开发人员可以更加方便地实现各种需求。 除了UI组件和功能组件,该模板还提供了一套完整的前端架构和开发规范。开发人员可以基于该模板进行二次开发,添加自己的业务逻辑和样式,以及进行自定义配置。同时,该模板还提供了详细的文档和示例代码,帮助开发人员快速入门和解决问题。 总的来说,Vue Element UI 后台管理系统首页模板是一个功能强大、易于使用、可定制的模板,适用于各种后台管理系统的快速开发。它能够帮助开发人员节省大量的时间和精力,提高开发效率,同时也提供了良好的用户体验和可维护性。 ### 回答2: VueElement UI是一对非常强大的前端开发工具组合,它们能够帮助我们快速构建出漂亮且功能丰富的后台管理系统。而在后台管理系统中,首页模板扮演着非常重要的角色。下面将用300字详细介绍VueElement UI配合的后台管理系统首页模板的特点。 VueElement UI的结合可以带来很多优势。首先,Vue框架本身具有数据驱动和组件化的特点,开发者可以通过创建组件、构建数据模型和实现数据绑定来快速搭建系统页面。而Element UI作为一个基于Vue的UI框架,提供了丰富的组件库,包含了按钮、卡片、表格、表单等常用组件,能够帮助我们更快速地构建页面。 在后台管理系统中,首页模板需要具备一些常见的功能和布局,以提供给用户友好的操作界面。通过VueElement UI可以轻松实现以下特点。 首先,首页模板需要包含一个侧边栏和顶部导航栏,侧边栏用于展示系统的菜单导航,而顶部导航栏用于显示用户信息和一些通知。VueElement UI提供了多种布局组件,可以快速实现这种侧边栏和导航栏的布局。 其次,首页模板需要展示一些重要的系统指标和数据统计信息,比如会员数量、订单数量、访问量等等。Vue的数据驱动特性可以很方便地将数据绑定到页面上,通过Element UI提供的卡片、图表等组件,可以直观地展示这些数据。 最后,首页模板还需要提供一些快捷入口和功能区块,比如最新订单、推荐产品、系统公告等。通过VueElement UI提供的组件,可以很容易地创建这些功能区块,并且通过路由导航等功能来实现相关的页面跳转和操作。 综上所述,VueElement UI的后台管理系统首页模板具有快速开发、易于扩展和美观实用等特点。通过组件化的开发方式和丰富的UI组件库,可以帮助我们快速构建出功能强大并且美观的后台管理系统。 ### 回答3: Vue Element UI 是一种基于Vue.js框架和Element UI组件库的后台管理系统首页模板。它提供了一套美观、易用、功能丰富的模板,方便开发者快速构建自己的后台管理系统Vue Element UI 的后台管理系统首页模板具有以下特点: 1. 响应式设计:该模板可以自动适应不同屏幕大小的设备,包括桌面电脑、平板电脑和手机。无论用户使用何种设备访问后台管理系统,都能得到良好的用户体验。 2. 多样化布局:该模板提供了多种布局方案,包括上下布局、左右布局等,适应不同的需求。用户可以根据自己的喜好和业务场景选择合适的布局。 3. 功能丰富:该模板集成了各种常见的后台管理系统功能模块,包括用户管理、角色权限管理、数据分析等,开发者可以基于这些功能模块快速搭建自己的后台系统。 4. 可定制化:该模板提供了丰富的主题和组件样式配置选项,开发者可以根据自己的需求进行定制。同时,该模板使用了Vue.js的组件化开发方式,方便扩展和组合。 5. 国际化支持:该模板提供了多语言支持,可以方便地将后台管理系统适配成不同语言版本,满足不同用户群体的需求。 总之,Vue Element UI 的后台管理系统首页模板是一种功能强大、易用灵活的模板,可以帮助开发者快速构建响应式、美观的后台管理系统。无论是初学者还是有经验的开发者,都可以轻松上手使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值