st779779

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

vue新项目初始化

vite构建

# 创建新项目
npm create vue@latest

# 安装依赖
npm install

# 启动项目
npm run dev

# 网络请求模块
npm i axios

# css预处理器 sass
npm i sass

# 安装 elementUI框架
npm install element-plus --save

# 安装 normalize.css  样式初始化文件
npm install normalize.css
#安装 Element Plus 图标集合。
npm install @element-plus/icons-vue
# 数据模拟
npm install mockjs

element-plus 修改css样式的时候 可以直接用
.el-button
去修改 .+组件名的的模式

配置element-plus

无论是全局引入 还是自动导入配置 要把css文件在 main.ts 引入

// main.ts 全局引入
import 'element-plus/dist/index.css'
// main.ts 全局引入
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')

初始化快速开始
https://element-plus.gitee.io/zh-CN/guide/quickstart.html

自动导入配置
npm install -D unplugin-vue-components unplugin-auto-import

// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

国际化配置中文模式

// main.ts
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'

app.use(ElementPlus, {
  locale: zhCn,
})

配置 vite项目环境变量

在根目录下新建两个文档

.env.dev

VITE_BASEURL="/api"
# 开发环境的接口

.env.prod

VITE_BASEURL="/api"
# 生产环境的接口

在package.json 修改

"scripts": {
    "dev": "vite --mode dev"
  }

使用 npm run dev 就会使用 .env.dev 里面配置的环境变量
使用 npm run build 就会使用 .env.prod 里面配置的环境变量

简单初始

删除 不需要的文件
这些文件都不需要
alt text

修改 css文件

# 安装 normalize.css  样式初始化文件
npm install normalize.css
# 在main.ts里面导入
import 'normalize.css'

文件后缀修改为scss

alt text

base.scss

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-weight: normal;
}

body {
  min-height: 100vh;
  color: var(--color-text);
  background: var(--color-background);
  transition:
    color 0.5s,
    background-color 0.5s;
  line-height: 1.6;
  font-family:
    Inter,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    'Fira Sans',
    'Droid Sans',
    'Helvetica Neue',
    sans-serif;
  font-size: 15px;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main.scss

/* 注意修改名称后这里原来的引入路径也要修改 */
@import './base.scss';

#app {
  max-width: 1280px;
  font-weight: normal;
}

main.ts文件 引入路径名称也要修改

import './assets/main.scss'

配置跨域

在 vite.config.ts 里面配置

// vite.config.ts
server: {
    proxy: {
      '/api': {
        // 配置需要代理的路径 --> 这里的意思是代理http://localhost:80/api/后的所有路由
        target: 'http://xxxx.xxxx.xxxx.xxxx:xx', // 目标地址 --> 服务器地址
        changeOrigin: true, // 允许跨域,
        ws: true, // 允许websocket代理
        // 重写路径 --> 作用与vue配置pathRewrite作用相同
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }

配置路由懒加载和前置路由守卫

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      redirect: '/home'  //让他跳转到 home 页面 输入地址会跳转到home
    },
    {
      path: '/home',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'home',
      component: () => import('@/views/AboutView.vue')  
      // 懒加载模式   进入/about这个地址的时候才会加载这个页面 而不是一开始就加载好
    }
  ]
})
//路由前置守卫,验证用户 身份检查权限
//to 即将进入目标路由对象 包含路由,参数,查询参数等
// from 当前导航正要离开的路由对象 , 从哪里来 包含了当前的路由信息
//next  函数 ,语言控制导航行为,可以接受一个参数 用与指定导航的目录路由
router.beforeEach((to, form, next) => {
    //如果登录了就让往下继续走 如果没有登录 跳转到登录页面
  if (userLogin) {
    next()
  } else {
    next('/login')
  }
})
export default router

封装 axios

// apis/index.ts  文件
import router from '@/router'
import axios, { AxiosError } from 'axios'
import type { AxiosRequestConfig } from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
export const request = axios.create()

// 返回的类型
export type BkResponse = {
  data: any
  code: number
  message: string
  succeed: boolean
}
//设置服务器根路径
request.defaults.baseURL = import.meta.env.VITE_BASEURL
//设置相应拦截器
export const $http = async (config: AxiosRequestConfig) => {
  const loadingInstance = ElLoading.service()
  try {
    const axiosResponse = await request<BkResponse>(config)
    const bkResponse = axiosResponse.data
    if (!bkResponse?.succeed) {
      //如果succeed 请求失败
      let errTitle: string = 'Error'
      if (bkResponse.code === 400) {
        //用户为授权
        errTitle = 'Unauthorized'
        ElMessage.error('未授权') //ui弹出
          router.push('/login')
      } else if (bkResponse.code === 403) {
        errTitle = 'ForBidden'
      } else if (bkResponse.code === 9999) {
        errTitle = '9999error'
      } else if (bkResponse.code === 500) {
        errTitle = 'ServeError'
      } else {
        errTitle = 'UnkownError'
      }
      // 如果返回有错误信息 没有返回错误信息 用 UnkownError
      const err = new Error(bkResponse?.message || 'UnkownError')
      err.name = errTitle
      // 抛出错误
      throw err
    }
    return bkResponse
  } catch (err) {
    if (err instanceof AxiosError) {
      ElMessage.error('网络错误') //ui弹出
    }
    throw err
  } finally {
    //关闭加载动画
    loadingInstance.close()
  }
}

// apis/login.ts 文件
import { $http } from '.'

/**
 * 登录接口
 */

export const loginApi = (data: { password: string; username: string }) => {
  return $http({
    method: 'post',
    url: '/admin/login',
    data
  })
}

使用 Mock来做拦截模拟数据

// main.ts 文件
// 引入mock文件
import './mock'
// src/mock/index.js  文件
import Mock from 'mockjs'
// import qs from 'qs'

// mock的配置
Mock.setup({
  // 随机延时500-1000毫秒
  timeout: '500-1000'
})
// 模拟接口,拦截请求
// 拦截请求,
// 第一个参数:url,使用正则去匹配
// 第二个参数:请求方式
// 第三个参数: 生成数据的函数
Mock.mock(/\/admin\/login/, 'post', config => {
  // 切分请求体
  // const queryString = config.url.split('?')[1]
  // 获取请求参数
  // const queryObject = qs.parse(queryString)
  //设置返回数据
  // const items = []
  //生成数据
  // for (let i = 0; i < +queryObject.pageSize; i++) {
  //   items.push(Mock.mock({
  //     id: '@id',
  //     name: '@ctitle(10,20)',
  //     desc: '@ctitle(4,10)',
  //     price: '@float(100,200,2,2)',
  //     // http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/clothes_goods_7.jpg
  //     picture: `http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/clothes_goods_${Mock.mock('@integer(1,8)')}.jpg`
  //   }))
  // }
  return {
    data: {'token':'123456789'},
    code: 200,
    message: '非常完美',
    succeed: true
  }
})
//生成随机数据
// 单个数据
Mock.mock('@integer(0,7)')
// 对象数据
Mock.mock({
    id: '@id',
    name: '@ctitle(2,4)'
})

使用flex样式快速布局

<!-- src/views/LoginView.vue 文件 -->
<script setup lang="ts">
import { User, Lock } from '@element-plus/icons-vue'
</script>
<template>
  <div id="login">
    <div class="login-box">
      <div class="logo">
        <el-image
          src="https://element-plus.gitee.io/images/element-plus-logo.svg"
          fit="fill"
          :lazy="true"
        ></el-image>
      </div>
      <el-form>
        <el-form-item>
          <el-input class="input" placeholder="请输入账号" :prefix-icon="User"></el-input>
        </el-form-item>
        <el-form-item>
          <el-input class="input" placeholder="请输入密码" :prefix-icon="Lock"></el-input>
        </el-form-item>
        <div class="btns">
          <el-button type="primary" class="btn">登录</el-button>
          <div class="btn reset">重置</div>
        </div>
      </el-form>
    </div>
  </div>
</template>
<style scoped lang="scss">
#login {
  height: 100vh;
  background: linear-gradient(to right, #fce38a, #f38181);
  display: flex;
  justify-content: center;
  align-items: center;
  .login-box {
    width: 360px;
    height: 450px;
    background-color: #fff;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    .logo {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 120px;
      height: 120px;
      border-radius: 50%;
      box-shadow: 0 0 4px 2px #f38181;
      margin-bottom: 40px;
      //overflow: hidden;
    }
    .el-form {
      width: 90%;
      margin-top: 30px;
      .input {
        height: 40px;
        :deep(.el-input__wrapper) {
          border-radius: 20px;
          border: 3px solid #333;
        }
      }
      .btns {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        .btn {
          width: 100%;
          height: 40px;
          border-radius: 22px;
          margin-bottom: 20px;
          cursor: pointer;
          text-align: center;
        }
      }
    }
  }
}
</style>

表单数据校验

// src/rules/userinfo.ts  文件
// 表单校验规则

//校验规则对象接口
import type { FormRules } from 'element-plus'

export const rules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 10, message: '长度3-10', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, max: 20, message: '长度6-20', trigger: 'blur' }
  ]
}

<!-- src/views/LoginView.vue 文件 -->
<script setup lang="ts">
import { User, Lock } from '@element-plus/icons-vue'
//form表单类接口
import type { FormInstance } from 'element-plus'
import { ref } from 'vue'
//引入校验规则 
import { rules } from '@/rules/userinfo'
//表单数据接口
interface Form {
  username: string
  password: string
}
//表单数据
const form = ref<Form>({
  username: '',
  password: ''
})
//form表单对象
const formRef = ref<FormInstance>()
//清空表单数据
const reset = () => {
  formRef.value?.resetFields()
}
// 登录功能
const login = async () => {
  const res = await loginApi(form.value)
  console.log(res)
}
</script>
<template>
  <div id="login">
    <div class="login-box">
    <!-- 绑定表单对象 表单数据 表单校验规则 -->>
      <el-form ref="formRef" :model="form" :rules="rules">
      <!-- 绑定表单校验规则名 -->
        <el-form-item prop="username">
          <el-input
            class="input"
            v-model="form.username"
            placeholder="请输入账号"
            :prefix-icon="User"
          ></el-input>
        </el-form-item>
         <!-- 绑定表单校验规则名 -->
        <el-form-item prop="password">
          <el-input
            class="input"
            v-model="form.password"
            placeholder="请输入密码"
            :prefix-icon="Lock"
          ></el-input>
        </el-form-item>
        <div class="btns">
          <el-button type="primary" class="btn"  @click="login">登录</el-button>
          <div class="btn reset" @click="reset">重置</div>
        </div>
      </el-form>
    </div>
  </div>
</template>

封装登录工具函数

// src/stores/userinfo.stor.ts 文件
import { request } from '@/apis'
import router from '@/router'
import { defineStore } from 'pinia'

export const useUserInfoStore = defineStore('userinfo-store', () => {
  //设置用户登录信息
  const setAuth = (token: string) => {
    //设置到请求头里面
    request.defaults.headers.common.Authorization = token
    localStorage.setItem('token', token)
  }
  //判断用户是否登录
  const authFormLocal = () => {
    const token = localStorage.getItem('token')
    if (token) {
      setAuth(token)
      //已登录
      return true
    }
    //没有登录
    return false
  }
  //清除本地用户信息
  const removeAuth = () => {
    //删除请求头里面的token
    delete request.defaults.headers.common.Authorization
    //删除本地存储的token
    localStorage.removeItem('token')
    //跳转到登录页面
    router.push('/login')
  }
  return {
    setAuth,
    authFormLocal,
    removeAuth
  }
})

<!-- src/views/LoginView.vue 文件 -->
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { useUserInfoStore } from '@/stores/userinfo.store'
import router from '@/router'
 
// 登录功能
const login = async () => {
  const res = await loginApi(form.value)
  //设置登录信息
  userInfoStore.setAuth(res.data.token)
  //弹窗提示登录成功
  ElMessage.success('登录成功')
//   跳转到home页面
  router.push('/home')
}
</script>

完善路由前置守卫

import { useUserInfoStore } from '@/stores/userinfo.store'
const usrInfoStore = useUserInfoStore()

// 给 login页面添加一个meta参数 noAth  在在守卫出不进行阻拦
routes: [
{
    path: '/login',
    name: 'login',
    meta: {
    //添加的参数
    noAuth: true
    }
}
]

router.beforeEach((to, form, next) => {
  if (to.meta.noAuth || usrInfoStore.authFormLocal()) {
    next()
  } else {
    router.push('login')
  }
})

异步引入 pinia 和 router

//main.ts 文件
//异步引入 pinia 和 router  因为 它们两个会互相引入 会报错
async function asyncRegister() {
  const createPinia = (await import('pinia')).createPinia
  app.use(createPinia())
  const router = (await import('@/router')).default
  app.use(router)
  app.mount('#app')
}
asyncRegister()

主页布局 使用动态组件

<!-- views/HomeView.vue组件 -->
<script setup lang="ts">
import AdminHeader from '@/components/layout/AdminHeader.vue'
import AdminMenu from '@/components/layout/AdminMenu.vue'
</script>

<template>
  <div class="home">
    <el-container>
      <el-header>
        <AdminHeader></AdminHeader>
      </el-header>
      <el-container>
        <el-affix>
          <el-aside width="200px"><AdminMenu /></el-aside>
        </el-affix>

        <el-main> </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<style lan="scss" scoped>
#home {
  min-height: 100vh;
}
.el-header {
  background-color: #1f1f1f;
  padding: 0;
}
.el-aside {
  background-color: #2b2c44;
  min-height: calc(100vh - 60px);
}
</style>

<!-- src\components\layout\AdminMenu.vue -->
<script setup lang="ts">
import type { Component } from 'vue'
import { House, User, Goods } from '@element-plus/icons-vue'
import { ElSubMenu, ElMenuItem } from 'element-plus'
interface MenuItem {
  id: number
  name: string
  index: string
  icon?: Component
  children?: MenuItem[]
}
//菜单假数据
const menulist: MenuItem[] = [
  {
    id: 1,
    name: '首页',
    index: '/home/admin-home',
    icon: House
  },
  {
    id: 2,
    name: '用户管理',
    index: '/home/users',
    icon: User
  },
  {
    id: 101,
    name: '商品管理',
    index: '/prouduct-management',
    icon: Goods,
    children: [
      {
        id: 102,
        name: '产品列表',
        index: '/home/goods'
      },
      {
        id: 103,
        name: '品牌列表',
        index: '/home/brand'
      },
      {
        id: 104,
        name: '类型列表',
        index: '/home/type'
      },
      {
        id: 105,
        name: '颜色列表',
        index: '/home/color'
      },
      {
        id: 106,
        name: '尺寸列表',
        index: '/home/size'
      }
    ]
  }
]
</script>
<template>
  <div id="menu">
    <el-menu
      active-text-color="#fff"
      background-color="#2b2c44"
      class="el-menu-vertical-demo"
      default-active="2"
      text-color="#fff"
      router
    >
      <component
        :is="item.children ? ElSubMenu : ElMenuItem"
        v-for="item in menulist"
        :key="item.id"
        :index="item.index"
      >
        <template v-if="item.children" #title>
          <el-icon v-if="item.icon">
            <component :is="item.icon"></component>
          </el-icon>
          <span>{{ item.name }}</span>
        </template>
        <template v-if="!item.children">
          <el-icon v-if="item.icon">
            <component :is="item.icon"></component>
          </el-icon>
          <span>{{ item.name }}</span>
        </template>
        <el-menu-item v-for="subItem in item.children" :key="subItem.id" :index="subItem.index">
          {{ subItem.name }}
        </el-menu-item>
      </component>
    </el-menu>
  </div>
</template>
<style scoped lang="scss"></style>

<!-- src\components\layout\AdminHeader.vue -->
<script setup lang="ts"></script>
<template>
 <div id="header">
   <div class="logo-box">adfad</div>
   <div class="right-box">
     <div class="title">后台管理系统</div>
     <div class="avatar-box">
       <el-avatar
         src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
         fit="fill"
       ></el-avatar>
     </div>
   </div>
 </div>
</template>
<style scoped lang="scss">
#header {
 background-color: #2b2c44;
 color: #fff;
 display: flex;
 justify-content: space-between;

 .logo-box {
   width: 200px;
   text-align: center;
   line-height: 60px;
   font-size: 22px;
   font-weight: bold;
   color: #e73267;
 }
 .right-box {
   flex: 1;
   display: flex;
   justify-content: space-between;
   align-items: center;
   font-size: 18px;
   .el-avatar {
     margin-right: 10px;
   }
 }
}
</style>

用户信息布局

// 给home添加二级路由
 {
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'admin-home',
          name: 'admin-home',
          component: () => import('@/components/home/AdminHome.vue')
        },
        {
          path: 'users',
          name: 'users',
          component: () => import('@/components/users/UserManagement.vue')
        },
        {
          path: 'goods',
          name: 'goods',
          component: () => import('@/components/goods/GoodsManagement.vue')
        }
      ]
    },
<!-- src\components\home\AdminHome.vue -->
<script setup lang="ts">
import AdminOverview from './adminHome/AdminOverview.vue'
import BarChart from './adminHome/BarChart.vue'
import LineChart from './adminHome/LineChart.vue'
import PieChart from './adminHome/PieChart.vue'
</script>
<template>
  <div class="wrap">
    <AdminOverview class="item"></AdminOverview>
    <bar-chart class="item"></bar-chart>
    <line-chart class="item"></line-chart>
    <pie-chart class="item"></pie-chart>
  </div>
</template>
<style scoped lang="scss">
.wrap {
  display: flex;
  flex-wrap: wrap;
  box-shadow: var(--el-box-shadow-light);
  .item {
    width: 50%;
    height: calc((100vh - 100px) / 2);
    min-height: 360px;
    border: 1px solid #eee;
    box-sizing: border-box;
  }
}
</style>

<!-- src\components\home\adminHome\AdminOverview.vue -->

<script setup lang="ts">
import { ref } from 'vue'
interface SingleData {
 id: number
 name: string
 number: string
}

interface OverviewData {
 allData: SingleData[]
 orderData: SingleData[]
}
const overviewData = ref<OverviewData>({
 allData: [
   {
     id: 1,
     name: '总销售额',
     number: '836,387'
   },
   {
     id: 2,
     name: '总访问量',
     number: '1,342,629'
   },
   {
     id: 3,
     name: '总支付量',
     number: '993,851'
   },
   {
     id: 4,
     name: '总收藏量',
     number: '1,031,753'
   }
 ],
 orderData: [
   {
     id: 1,
     name: '今日订单数',
     number: '264'
   },
   {
     id: 2,
     name: '累计金额',
     number: '3,564'
   },
   {
     id: 3,
     name: '本月订单数',
     number: '4,523'
   },
   {
     id: 4,
     name: '累计金额',
     number: '125,551'
   }
 ]
})
</script>
<template>
 <div id="overview">
   <div class="userinfo">
     <el-avatar
       src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
       fit="fill"
     ></el-avatar>
     <span class="username">xxx</span>
   </div>
   <div class="overview-list">
     <div class="overview-item" v-for="item in overviewData.allData" :key="item.id">
       <div class="title">{{ item.name }}</div>
       <div class="num">{{ item.number }}</div>
     </div>
   </div>
   <div class="overview-list">
     <div class="overview-item" v-for="item in overviewData.allData" :key="item.id">
       <div class="title">{{ item.name }}</div>
       <div class="num">{{ item.number }}</div>
     </div>
   </div>
 </div>
</template>
<style scoped lang="scss">
#overview {
 padding: 30px;
 .userinfo {
   display: flex;
   align-items: center;

   .username {
     margin-left: 10px;
   }
 }
 .overview-list {
   margin-top: 40px;
   display: flex;
   justify-content: space-between;
   .overview-item {
     width: 22%;
     display: flex;
     flex-direction: column;
     justify-content: center;
     align-items: center;
     box-shadow: var(--el-box-shadow-light);
     border-radius: 10px;
     padding: 20px;
     .title {
       font-weight: 700;
       margin-bottom: 10px;
     }
     .num {
       font-size: 18px;
     }
   }
 }
}
</style>

用户信息展示

<!-- src\components\users\UserManagement.vue -->
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import { ref } from 'vue'
const keyword = ref<string>('')
interface User {
 date: string
 name: string
 address: string
}

const handleEdit = (index: number, row: User) => {
 console.log(index, row)
}

interface UserData {
 avater: string
 createTime: number
 email: string
 gender: number
 id: number
 integration: number
 isDeleted: 0 | 1
 nickname: string
 password: string
 phoneNumber: string
 status: 0 | 1
 updateTime: number
 username: string
}
const tableData: UserData[] = [
 {
   avater: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
   createTime: Date.now(),
   email: '1237@qq.com',
   gender: 0,
   id: 1,
   integration: 0,
   isDeleted: 1,
   nickname: '你是最棒的',
   password: '123456',
   phoneNumber: '123456',
   status: 1,
   updateTime: Date.now(),
   username: '123456'
 },
 {
   avater: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
   createTime: Date.now(),
   email: '1237@qq.com',
   gender: 0,
   id: 2,
   integration: 0,
   isDeleted: 1,
   nickname: '你是最棒的',
   password: '123456',
   phoneNumber: '123456',
   status: 1,
   updateTime: Date.now(),
   username: '123456'
 },
 {
   avater: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
   createTime: Date.now(),
   email: '1237@qq.com',
   gender: 0,
   id: 3,
   integration: 0,
   isDeleted: 1,
   nickname: '你是最棒的',
   password: '123456',
   phoneNumber: '123456',
   status: 1,
   updateTime: Date.now(),
   username: '123456'
 },
 {
   avater: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
   createTime: Date.now(),
   email: '1237@qq.com',
   gender: 0,
   id: 4,
   integration: 0,
   isDeleted: 1,
   nickname: '你是最棒的',
   password: '123456',
   phoneNumber: '123456',
   status: 1,
   updateTime: Date.now(),
   username: '123456'
 }
]
</script>
<template>
 <div id="users">
   <el-breadcrumb separator="/">
     <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
     <el-breadcrumb-item>用户管理</el-breadcrumb-item>
   </el-breadcrumb>

   <el-card>
     <div class="header">
       <el-input
         v-model="keyword"
         style="max-width: 600px"
         placeholder="请输入关键词"
         class="input-with-select"
       >
         <template #append>
           <el-button :icon="Search" />
         </template>
       </el-input>
     </div>
     <el-table :data="tableData" style="width: 100%">
       <el-table-column prop="id" label="id" width="180"></el-table-column>
       <el-table-column prop="username" label="用户名"></el-table-column>
       <el-table-column prop="nickname" label="昵称"></el-table-column>
       <el-table-column prop="gender" label="性别">
         <template #default="scope">
           <div style="display: flex; align-items: center">
             <span>{{ scope.row.gender === 0 ? '男' : '女' }}</span>
           </div>
         </template>
       </el-table-column>
       <el-table-column label="头像" width="180">
         <template #default="scope">
           <div style="display: flex; align-items: center">
             <el-avatar
               icon="el-icon-user-solid"
               size="large"
               shape="circle"
               :src="scope.row.avater"
               fit="fill"
             ></el-avatar>
           </div>
         </template>
       </el-table-column>
       <el-table-column prop="email" label="邮箱"></el-table-column>
       <el-table-column prop="phoneNumber" label="手机号"></el-table-column>
       <el-table-column label="状态" width="180">
         <template #default="scope">
           <div style="display: flex; align-items: center">
             <el-switch v-model="scope.row.isDeleted" />
           </div>
         </template>
       </el-table-column>

       <el-table-column label="操作">
         <template #default="scope">
           <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
         </template>
       </el-table-column>
     </el-table>
     <!-- 分页数据 -->
     <el-pagination small layout="prev, pager, next" :total="10" />

     <!-- 可选分页数据 -->
     <!-- <el-pagination
     v-model:current-page="当前页"
     v-model:page-size="页面数据"
     :page-sizes="[100, 200, 300, 400]"

     layout="total, sizes, prev, pager, next, jumper"
     :total="总数据"
     @size-change="条目数改变的时候触发"
     @current-change="handleCurrentChange"
   /> -->
   </el-card>
 </div>
</template>
<style scoped lang="scss">
#users {
 .el-breadcrumb {
   margin-bottom: 20px;
 }
 .header {
   .el-input {
     width: 30%;
   }
 }
}
</style>

posted on 2024-04-11 21:45  xirang熙攘  阅读(42)  评论(0编辑  收藏  举报