当前位置:   article > 正文

Ant-design-vue

ant-design-vue

一、集成ant-design-vue

官网地址:Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js

yarn add ant-design-vue
  • 在main.ts文件中引入antd

  1. import Antd from "ant-design-vue"
  2. import "ant-design-vue/dist/antd.css"
  3. app.use(Antd)

二、登录模块

1、登录静态页面
  1. <template>
  2.  <div style="background: #001529; height:100vh">
  3.    <a-card title="用户登录" :bordered="true" class="loginBox">
  4.      <a-form
  5.        :model="formState"
  6.        name="basic"
  7.        :label-col="{ span: 8 }"
  8.        :wrapper-col="{ span: 16 }"
  9.        autocomplete="off"
  10.        @finish="onFinish"
  11.        @finishFailed="onFinishFailed"
  12.      >
  13.        <a-form-item
  14.          label="账号"
  15.          name="account"
  16.          :rules="[{ required: true, message: '请输入账号!' }]"
  17.        >
  18.          <a-input v-model:value="formState.account" />
  19.        </a-form-item>
  20.        <a-form-item
  21.          label="密码"
  22.          name="password"
  23.          :rules="[{ required: true, message: '请输入密码!' }]"
  24.        >
  25.          <a-input-password v-model:value="formState.password" />
  26.        </a-form-item>
  27.        <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
  28.          <a-button type="primary" html-type="submit">登录</a-button>
  29.        </a-form-item>
  30.      </a-form>
  31.    </a-card>
  32.  </div>
  33. </template>
  34. <script lang="ts">
  35. interface FormState {
  36.  account: string;
  37.  password: string;
  38. }
  39. import { reactive } from "vue";
  40. export default {
  41.  setup() {
  42.    const formState = reactive<FormState>({
  43.      account: "",
  44.      password: "",
  45.   });
  46.    const onFinish = (values: any) => {
  47.      console.log("Success:", values);
  48.   };
  49.    const onFinishFailed = (errorInfo: any) => {
  50.      console.log("Failed:", errorInfo);
  51.   };
  52.    return {
  53.      formState,
  54.      onFinish,
  55.      onFinishFailed,
  56.   };
  57. },
  58. };
  59. </script>
  60. <style>
  61.    .loginBox{
  62.        width: 380px;
  63.        position:absolute;
  64.        top:50%;
  65.        left: 50%;
  66.        transform: translate(-50%,-50%);
  67.   }
  68. </style>
2、登录接口编写
  • 安装axios

yarn add axios
  • 定义UserType接口

  1. export default interface UserType{
  2.    account: string,
  3.    password:string
  4. }
  • 编写登录接口

  1. import axios from 'axios'
  2. axios.defaults.baseURL="http://www.zhaijizhe.cn:3001"
  3. import UserType from '../../type/UserType'
  4. export default{
  5.    loginApi:(data:UserType)=>axios.post("/users/login",data)
  6. }
  • 汇总api

  1. import users from './moudules/users'
  2. export default{
  3.    users
  4. }
3、登录组件中调用api方法

在Login.vue组件的onFinish函数中调用登录api方法实现用户登录

  1. import { reactive } from "vue";
  2. import {useRouter} from 'vue-router'
  3. import { message } from 'ant-design-vue';
  4. import api from "../http/api";
  5. export default {
  6.  setup() {
  7.    const router=useRouter() //实例化路由对象
  8.    const formState = reactive<FormState>({
  9.      account: "",
  10.      password: "",
  11.   });
  12.    const onFinish = async(values: any) => {
  13.       const result=await api.users.loginApi(values)
  14.       if(result.data.code){
  15.         //将token保存到localStorage中
  16.         localStorage.setItem('token',result.data.data.token)
  17.         //将用户信息保存到状态机中
  18.         //进行路由跳转
  19.         router.replace({
  20.            path:'/'
  21.         })
  22.       }else{
  23.          message.error('用户名或密码有误!');
  24.       }
  25.   };
  26. }
4、编写拦截器

在src/http下新建interceptor.js文件,将axios拦截器的代码编写在这里

  1. import axios from "axios";
  2. import { message } from 'ant-design-vue';
  3. axios.interceptors.request.use((config:any)=>{
  4. //携带token到请求头
  5. config.headers.Authorization=localStorage.getItem('token')
  6. return config;
  7. })
  8. axios.interceptors.response.use(res=>{
  9. console.log('------拦截器-------');
  10. if(res.data.code==1){
  11. return res;
  12. }else{
  13. message.error( res.data.msg);
  14. return Promise.reject(res);
  15. }
  16. },err=>{
  17. switch(err.response.status){
  18. case 500:
  19. message.error("服务端后台出现500错误");
  20. break;
  21. case 401:
  22. message.error("服务端后台出现401错误");
  23. break;
  24. case 404:
  25. message.error("没有找到服务端相应资源");
  26. break;
  27. default:
  28. }
  29. return Promise.reject(err);
  30. })

三、后台首页

1、后台首页设计
  1. <template>
  2. <a-layout>
  3. <a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible>
  4. <div class="logo">
  5. <img src="../assets/logo.png" alt="">
  6. 企业管理系统
  7. </div>
  8. <a-menu v-model:selectedKeys="selectedKeys" theme="dark" mode="inline">
  9. <a-menu-item key="1">
  10. <user-outlined />
  11. <span>nav 1</span>
  12. </a-menu-item>
  13. <a-menu-item key="2">
  14. <video-camera-outlined />
  15. <span>nav 2</span>
  16. </a-menu-item>
  17. <a-menu-item key="3">
  18. <upload-outlined />
  19. <span>nav 3</span>
  20. </a-menu-item>
  21. </a-menu>
  22. </a-layout-sider>
  23. <a-layout>
  24. <a-layout-header style="background: #fff; padding: 2">
  25. <menu-unfold-outlined
  26. v-if="collapsed"
  27. class="trigger"
  28. @click="() => (collapsed = !collapsed)"
  29. />
  30. <menu-fold-outlined v-else class="trigger" @click="() => (collapsed = !collapsed)" />
  31. </a-layout-header>
  32. <a-layout-content
  33. :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '580px' }"
  34. >
  35. Content
  36. </a-layout-content>
  37. </a-layout>
  38. </a-layout>
  39. </template>
  40. <script lang="ts">
  41. import {
  42. UserOutlined,
  43. VideoCameraOutlined,
  44. UploadOutlined,
  45. MenuUnfoldOutlined,
  46. MenuFoldOutlined,
  47. } from '@ant-design/icons-vue';
  48. import { defineComponent, ref } from 'vue';
  49. export default defineComponent({
  50. components: {
  51. UserOutlined,
  52. VideoCameraOutlined,
  53. UploadOutlined,
  54. MenuUnfoldOutlined,
  55. MenuFoldOutlined,
  56. },
  57. setup() {
  58. return {
  59. selectedKeys: ref<string[]>(['1']),
  60. collapsed: ref<boolean>(false),
  61. };
  62. },
  63. });
  64. </script>
  65. <style>
  66. .logo{
  67. height: 50px;
  68. color: white;
  69. font-size: 18px;
  70. line-height: 50px;
  71. text-align: center;
  72. }
  73. .logo img{
  74. width: 40px;
  75. height: 40px;
  76. border-radius: 50%;
  77. }
  78. #components-layout-demo-custom-trigger .trigger {
  79. font-size: 18px;
  80. line-height: 64px;
  81. padding: 0 24px;
  82. cursor: pointer;
  83. transition: color 0.3s;
  84. }
  85. #components-layout-demo-custom-trigger .trigger:hover {
  86. color: #1890ff;
  87. }
  88. #components-layout-demo-custom-trigger .logo {
  89. height: 32px;
  90. background: rgba(255, 255, 255, 0.3);
  91. margin: 16px;
  92. }
  93. .site-layout .site-layout-background {
  94. background: #fff;
  95. }
  96. </style>
2、二级路由配置

首先在<a-menu-item>标签的key属性中写上二级路由的path路径保持一致

其次在<a-menu>标签上绑定@click="handClick"方法

  1. <a-menu
  2. v-model:selectedKeys="selectedKeys"
  3. theme="dark"
  4. mode="inline"
  5. @click="handClick">
  6. <a-menu-item key="/userList">
  7. <user-outlined />
  8. <span>用户管理</span>
  9. </a-menu-item>
  10. <a-menu-item key="/categoryList">
  11. <video-camera-outlined />
  12. <span>分类管理</span>
  13. </a-menu-item>
  14. <a-menu-item key="/goodsList">
  15. <upload-outlined />
  16. <span>商品管理</span>
  17. </a-menu-item>
  18. </a-menu>
  19. import {useRouter} from 'vue-router'
  20. export default defineComponent({
  21. setup() {
  22. const router=useRouter()
  23. const handClick=(item:any)=>{
  24. router.push(item.key)
  25. }
  26. return {
  27. handClick
  28. };
  29. },
  30. })

设置二级路由出口

  1. <a-layout-content
  2. :style="{ margin: '24px 16px', padding: '24px', background: '#fff',
  3. minHeight: '580px' }">
  4. <!--二级路由出口 -->
  5. <router-view></router-view>
  6. </a-layout-content>
3、配置路由守卫

在src/router/index.ts中配置路由守卫

  1. router.beforeEach(to=>{
  2. const token=localStorage.getItem("token")
  3. if(!token&&to.path!=="/login"){
  4. return "/login"
  5. }
  6. })

四、动态菜单和路由挂载

1、动态菜单
  • 首先通过创建pinia仓库

  1. //导入defineStore函数
  2. import {defineStore} from 'pinia'
  3. import api from '@/api'
  4. import IUserState from '@/types/IUserState'
  5. import {RouteRecordRaw} from 'vue-router'
  6. import {getViews} from '@/utils/routedync'
  7. //通过该函数创建store对象
  8. const useUserStore=defineStore('users',{
  9. state:():IUserState=>{
  10. return{
  11. token:'',
  12. permissionList:[]
  13. }
  14. },
  15. getters:{
  16. //返回首页路由对象
  17. getHomeRoute(state:IUserState){
  18. let routeObj:RouteRecordRaw={
  19. path:'/',
  20. component:()=>import('@/views/Home.vue'),
  21. children:[]
  22. }
  23. let ary:Array<RouteRecordRaw>=[]
  24. state.permissionList.forEach((item:any)=>{
  25. if(item.children){
  26. item.children.forEach((subItem:any)=>{
  27. ary.push({
  28. path:subItem.path,
  29. component:getViews(`../views${subItem.path}.vue`)
  30. })
  31. })
  32. }
  33. })
  34. routeObj.children=ary
  35. return routeObj
  36. }
  37. },
  38. actions:{
  39. setToken(token:string){
  40. this.token=token
  41. },
  42. async getAuthMenuAsync(){
  43. const result=await api.users.getAuthMenus()
  44. this.permissionList=result.data.data
  45. console.log('权限',result.data.data);
  46. }
  47. },
  48. persist:{
  49. enabled:true,
  50. strategies:[
  51. {
  52. key:'users',
  53. storage:localStorage
  54. }
  55. ]
  56. }
  57. })
  58. export default useUserStore
  • 其中要注意,这里边不能使用路由懒加载,动态路由的组件地址全部获取,可以在utils文件夹下编写routedync.ts

  1. export function getViews(path:string){
  2. let modules=import.meta.glob('../**/*.vue')
  3. return modules[path]
  4. }
  • 当然,还学要在store文件夹下创建index.ts

  1. import {createPinia} from 'pinia'
  2. import piniaPluginPersist from 'pinia-plugin-persist'
  3. const pinia=createPinia()
  4. pinia.use(piniaPluginPersist)
  5. export default pinia
  • 然后在main.ts中引入

  1. import {createApp} from 'vue'
  2. import App from '@/App.vue'
  3. import Antd from "ant-design-vue"
  4. import "ant-design-vue/dist/antd.css"
  5. import router from './router'
  6. import pinia from './store'
  7. import * as icons from '@ant-design/icons-vue'
  8. const app=createApp(App)
  9. for (const i in icons) {
  10. app.component(i, icons[i])
  11. }
  12. app.use(pinia) //设置pinina插件到vue实例上
  13. app.use(Antd) //设置antd插件到vue实例上
  14. app.use(router) //设置router插件到vue实例上
  15. app.mount('#app')
  • 在Home.vue中调用并渲染

  1. <template>
  2. <div class="container">
  3. <div class="sider">
  4. <!-- <ul>
  5. <li>
  6. <router-link to="/users">用户管理</router-link>
  7. </li>
  8. <li>
  9. <router-link to="/product">商品管理</router-link>
  10. </li>
  11. </ul> -->
  12. <a-menu
  13. mode="inline"
  14. theme="dark">
  15. <a-sub-menu v-for="item in permissionList" :key="item._id">
  16. <template #icon>
  17. <component :is="item.icon"></component>
  18. </template>
  19. <template #title>{{item.title}}</template>
  20. <a-menu-item :key="subItem._id" v-for="subItem in item.children" @click="go(subItem.path)">
  21. <template #icon>
  22. <component :is="subItem.icon"></component>
  23. </template>
  24. <span>{{ subItem.title}}</span>
  25. </a-menu-item>
  26. </a-sub-menu>
  27. </a-menu>
  28. <!-- {{ permissionList }} -->
  29. </div>
  30. <div class="content">
  31. <!-- 二级路由出口 -->
  32. <router-view></router-view>
  33. </div>
  34. </div>
  35. </template>
  36. <script lang='ts' setup>
  37. import {Menu} from 'ant-design-vue'
  38. import useUserStore from '@/store/users';
  39. import {useRouter} from 'vue-router'
  40. const store=useUserStore()
  41. const nav=useRouter()
  42. const permissionList=store.permissionList
  43. const go=(path:string)=>{
  44. console.log('path',path);
  45. nav.push({
  46. path
  47. })
  48. }
  49. </script>
2、图标的动态渲染
  • 下载完成后在 main.js 中添加

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import * as Icons from '@ant-design/icons-vue'
  4. const app = createApp(App)
  5. // 注册图标组件
  6. for (const i in Icons) {
  7. app.component(i, Icons[i])
  8. }
  9. app.mount('#app)
  • 在vue文件中使用 <component :is="icon">

  1. <a-sub-menu v-for="item in permissionList" :key="item._id">
  2. <template #icon>
  3. <component :is="item.icon"></component>
  4. </template>
  5. </a-sub-menu>
3、动态路由挂载

在router/index.ts中编写动态路由挂载方法

  1. import {RouteRecordRaw,createRouter,createWebHashHistory,createWebHistory} from 'vue-router'
  2. //定义路由规则对象集合
  3. import api from '@/api'
  4. import {message} from 'ant-design-vue'
  5. // import useUserStore from '@/store/users'
  6. const routes:Array<RouteRecordRaw>=[
  7. {
  8. path:'/login',
  9. name:'login',
  10. component:()=>import('@/views/Login.vue')
  11. },
  12. {
  13. path:'/',
  14. redirect:'/home'
  15. },
  16. {
  17. path:'/home',
  18. component:()=>import('@/views/Home.vue'),
  19. }
  20. ]
  21. //这里是关键代码
  22. const dyncRoute=()=>{
  23. const store=useUserStore()
  24. //完成向pinia发送请求,然后获取权限
  25. store.getAuthMenuAsync()
  26. //调用首页路由对象
  27. const homeRoute:RouteRecordRaw=store.getHomeRoute
  28. //添加到路由对象上
  29. router.addRoute(homeRoute)
  30. console.log('路由集合',router.getRoutes());
  31. }
  32. //定义router对象
  33. const router=createRouter({
  34. routes:routes,
  35. //history:createWebHashHistory() //hash模式,
  36. history:createWebHistory() //history模式
  37. })
  38. router.beforeEach(async(to,from,next)=>{
  39. //执行useUserStore方法
  40. if(to.path=="/login"){
  41. next()
  42. }else{
  43. //没有登录直接进入
  44. //获取token
  45. let token=localStorage.getItem('token')
  46. console.log('token是否',token);
  47. //如果没有token
  48. if(!token){
  49. //跳转到登录页面上去
  50. next("/login")
  51. }else{
  52. try {
  53. await api.users.getUserInfo()
  54. dyncRoute()
  55. //继续进行导航
  56. next()
  57. } catch (error) {
  58. message.error('token已经失效,请重新登录')
  59. next('/login')
  60. }
  61. }
  62. }
  63. })
  64. export default router
4、页面刷新路由丢失

路由丢失的主要原因是因为执行顺序的问题,解决办法是将动态路由的添加移到main.ts中 ,删除掉router/index.ts中的动态路由添加,一定要注意动态路由的添加必须放在app.use(router)之前,app.use(pinia)之后

  1. import {createApp} from 'vue'
  2. import App from '@/App.vue'
  3. import Antd from "ant-design-vue"
  4. import "ant-design-vue/dist/antd.css"
  5. import router from './router'
  6. import pinia from './store'
  7. import * as icons from '@ant-design/icons-vue'
  8. import useUserStore from '@/store/users'
  9. import {RouteRecordRaw} from 'vue-router'
  10. const app=createApp(App)
  11. for (const i in icons) {
  12. app.component(i, icons[i])
  13. }
  14. const dyncRoute=()=>{
  15. const store=useUserStore()
  16. //完成向pinia发送请求,然后获取权限
  17. store.getAuthMenuAsync()
  18. //调用首页路由对象
  19. const homeRoute:RouteRecordRaw=store.getHomeRoute
  20. //添加到路由对象上
  21. router.addRoute(homeRoute)
  22. console.log('路由集合',router.getRoutes());
  23. }
  24. app.use(pinia) //设置pinina插件到vue实例上
  25. app.use(Antd) //设置antd插件到vue实例上
  26. dyncRoute()
  27. //在app.use(router)之前进行路由添加调用,可以解决页面刷新的问题
  28. app.use(router) //设置router插件到vue实例上
  29. app.mount('#app')

五、选项卡

整体的思路就是封装一个选项卡组件

1、新建选项卡store
  1. import {defineStore} from 'pinia'
  2. import {RouteMeta} from 'vue-router'
  3. import {unique} from '@/utils/aryutils'
  4. interface IRouteType{
  5. tabAry:Array<RouteMeta>
  6. }
  7. const useTabStore=defineStore('tabs',{
  8. state:():IRouteType=>{
  9. return{
  10. tabAry:[]
  11. }
  12. },
  13. getters:{
  14. getTabAry(state){
  15. return state.tabAry
  16. }
  17. },
  18. actions:{
  19. addTabs(item:RouteMeta){
  20. this.tabAry.push(item)
  21. //删除掉数组中的空对象
  22. var filterNullAry = this.tabAry.filter(value => Object.keys(value).length !== 0);
  23. // let index=0
  24. // this.tabAry.forEach((value:RouteMeta,i:number)=>{
  25. // if( Object.keys(value).length==0){
  26. // index=i;
  27. // }
  28. // })
  29. // this.tabAry[index]={title:'工作台',path:'/home/workplace'}
  30. // //按照对象属性去重
  31. let uniqueAray= unique(this.tabAry,"title")
  32. this.tabAry=uniqueAray
  33. },
  34. removeTab(title:string){
  35. const ary=this.tabAry.filter((item:RouteMeta)=>{
  36. return item.title!=title
  37. })
  38. this.tabAry=ary
  39. }
  40. }
  41. })
  42. export default useTabStore
  43. 注意:这里封装一个按照对象进行数组中去重的方法
  44. export const unique=(arr:any,u_key:string)=> {
  45. let map = new Map()
  46. arr.forEach((item:any,index:number)=>{
  47. if (!map.has(item[u_key])){
  48. map.set(item[u_key],item)
  49. }
  50. })
  51. return [...map.values()]
  52. }
2、在路由守卫函数中添加选项卡
  1. router.beforeEach(async(to,from,next)=>{
  2. //执行useTabStore方法
  3. const store=useTabStore()
  4. if(to.path=="/login"){
  5. next()
  6. }else{
  7. //没有登录直接进入
  8. //获取token
  9. let token=localStorage.getItem('token')
  10. console.log('token是否',token);
  11. //如果没有token
  12. if(!token){
  13. //跳转到登录页面上去
  14. next("/login")
  15. }else{
  16. try {
  17. await api.users.getUserInfo()
  18. store.addTabs(to.meta) //关键代码
  19. next()
  20. } catch (error) {
  21. message.error('token已经失效,请重新登录')
  22. next('/login')
  23. }
  24. }
  25. }
  26. })
3、封装选项卡组件
  1. <template>
  2. <div>
  3. <div class="tab" v-for="(item,index) in tabs"
  4. :key="index" @click="go(item.path)">{{item.title }}<span style="margin-left:10px" @click="removeTab(item.title)">&times;</span></div>
  5. </div>
  6. </template>
  7. <script lang='ts' setup>
  8. import { defineProps } from "vue";
  9. import { RouteMeta,useRouter } from "vue-router";
  10. import useTabStore from '@/store/tabs'
  11. defineProps<{ tabs: Array<RouteMeta> }>();
  12. const router=useRouter()
  13. const store=useTabStore()
  14. const go=(path:string)=>{
  15. router.push(path)
  16. }
  17. const removeTab=(title:string)=>{
  18. store.removeTab(title)
  19. }
  20. </script>
  21. <style lang='scss' scoped>
  22. .tab {
  23. cursor: pointer;
  24. display: inline-block;
  25. font-size: 14px;
  26. font-weight: 500;
  27. height: 40px;
  28. line-height: 40px;
  29. text-align: center;
  30. padding: 0 15px;
  31. }
  32. </style>
4、在Home组件中引用
  1. </template>
  2. <div class="content">
  3. <TabComponet :tabs="tabs"></TabComponet>
  4. <!-- 二级路由出口 -->
  5. <router-view></router-view>
  6. </div>
  7. </template>
  8. <script lang='ts' setup>
  9. import { Menu } from "ant-design-vue";
  10. import useUserStore from "@/store/users";
  11. import { useRouter } from "vue-router";
  12. import TabComponet from "@/components/TabComponet.vue";
  13. import useTabStore from "@/store/tabs";
  14. import {storeToRefs} from 'pinia'
  15. const store1 = useTabStore();
  16. const tabs = storeToRefs(store1).getTabAry;
  17. const store = useUserStore();
  18. const nav = useRouter();
  19. const permissionList = store.permissionList;
  20. const go = (path: string) => {
  21. console.log("path", path);
  22. nav.push({
  23. path,
  24. });
  25. };
  26. </script>

六、用户管理

1、用户列表
  1. <template>
  2. <a-table
  3. :dataSource="list"
  4. :columns="columns">
  5. <template #bodyCell="{ column, record }">
  6. <template v-if="column.key === 'imgUrl'">
  7. <a-avatar :src="record.imgUrl" />
  8. </template>
  9. <template v-if="column.key === 'role'">
  10. {{record.role.name}}
  11. </template>
  12. <template v-if="column.key === 'state'">
  13. {{record.state==1?'正常':'禁用'}}
  14. </template>
  15. <template v-if="column.key === 'createDate'">
  16. {{record.createDate.substring(0,10)}}
  17. </template>
  18. </template>
  19. </a-table>
  20. </template>
  21. <script lang="ts">
  22. import { reactive, toRefs,onMounted} from "vue";
  23. import api from '../http/api'
  24. import UserType from '../type/UserType';
  25. export default {
  26. setup() {
  27. const columns = [
  28. {
  29. title: "用户名",
  30. dataIndex: "account",
  31. key: "account",
  32. },
  33. {
  34. title: "邮箱",
  35. dataIndex: "email",
  36. key: "email",
  37. },
  38. {
  39. title: "创建时间",
  40. dataIndex: "createDate",
  41. key: "createDate",
  42. },
  43. {
  44. title:'角色',
  45. dataIndex:'role',
  46. key:'role',
  47. },
  48. {
  49. title:'头像',
  50. dataIndex:'imgUrl',
  51. key:'imgUrl',
  52. },
  53. {
  54. title:'状态',
  55. dataIndex:'state',
  56. key:'state'
  57. }
  58. ];
  59. const data = reactive<{list:Array<UserType>}>({
  60. list:[]
  61. });
  62. onMounted(async()=>{
  63. let result=await api.users.getAccountListApi()
  64. console.log(result.data);
  65. data.list=result.data.data
  66. })
  67. return {
  68. columns,
  69. ...toRefs(data),
  70. };
  71. },
  72. };
  73. </script>
2、删除用户
  • 给columns列表增加操作项

  1. const columns = [
  2. {
  3. title: '操作',
  4. dataIndex: 'operation',
  5. key:'operation'
  6. },
  7. ];
  • 增加template模板项

  1. <template v-if="column.key === 'operation'">
  2. <a-popconfirm
  3. v-if="list.length"
  4. title="您确定要删除吗?"
  5. @confirm="deleteUser(record._id)"
  6. >
  7. <a>删除</a>
  8. </a-popconfirm>
  9. </template>
  • 编写deleteUser方法

  1. const deleteUser=async(id:number)=>{
  2. let result=await api.users.deleteAccountApi(id)
  3. if(result.data.code){
  4. console.log(result.data.data);
  5. findAccount()
  6. }
  7. }
  8. const findAccount=async()=>{
  9. let result=await api.users.getAccountListApi()
  10. data.list=result.data.data
  11. }
  12. onMounted(()=>{
  13. findAccount()
  14. })

七、分类管理

1、后台api编写
  1. import axios from 'axios'
  2. axios.defaults.baseURL="http://www.zhaijizhe.cn:3001"
  3. export default{
  4. getAllCategroyApi:()=>axios.get("/categroy/findAllCategroy")
  5. }
2、组件
  1. <template>
  2. <a-table
  3. :columns="columns"
  4. :data-source="list"
  5. :row-selection="rowSelection"
  6. />
  7. </template>
  8. <script lang="ts">
  9. import { reactive, toRefs, onMounted } from "vue";
  10. import CategoryType from "../type/CategoryType";
  11. import api from "../http/api";
  12. export default {
  13. setup() {
  14. const columns = [
  15. {
  16. title: "名称",
  17. dataIndex: "label",
  18. key: "label",
  19. },
  20. {
  21. title: "值",
  22. dataIndex: "value",
  23. key: "value",
  24. }
  25. ];
  26. const data = reactive<{ list: Array<CategoryType> }>({
  27. list: [],
  28. });
  29. onMounted(async () => {
  30. const result = await api.category.getAllCategroyApi();
  31. data.list = result.data.data;
  32. });
  33. return {
  34. ...toRefs(data),
  35. columns
  36. };
  37. },
  38. };
  39. </script>
  40. <style>
  41. </style>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/475139
推荐阅读
相关标签
  

闽ICP备14008679号