当前位置: 首页 > article >正文

【VUE】会员管理(增删改查)

前端

router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import {userInfoStore} from "@/stores/user.js";

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/LoginView.vue')
    },
    {
      path: '/admin',
      name: 'admin',
      component: () => import('../views/AdminView.vue'),
      children: [
        {
          path: "",
          redirect: {name: "home"}
        },
        {
          path: "home",
          name: "home",
          component: () => import('../views/HomeView.vue')
        },
        {
          path: "vip",
          name: "vip",
          component: () => import('../views/VipView.vue')
        }
      ]
    }
  ]
})
router.beforeEach(function (to,from,next) {
  // 1.访问登录页面,不需要登录就可以直接去查看
  if (to.name === "login") {
    next()
    return
  }
  // 2.检查用户登录状态,登录成功,继续往后走next();未登录,跳转至登录页面
  // let username = localStorage.getItem("name")
  const store = userInfoStore()
  if (!store.userId){
    next({name:"login"})
    return;
  }
  // 3.登录成功且获取到用户信息,继续向后访问
  next()
})

export default router

views/VipView.vue

<template>
  <h1>会员管理</h1>
  <button @click="doEdit">编辑</button>
  <table border="1">
    <thead>
    <tr>
      <th>ID</th>
      <th>姓名</th>
      <th>级别</th>
      <th>积分</th>
      <th>操作</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="(item,idx) in dataList">
      <td>{{ item.id }}</td>
      <td>{{ item.name }}</td>
      <td>{{ item.level_text }}</td>
      <td>{{ item.score }}</td>
      <td>
        <a>编辑</a>
        |
        <a>删除</a>
      </td>
    </tr>
    </tbody>
  </table>

  <div v-show="dialog" class="mask"></div>
  <div v-show="dialog" class="dialog">
    <input type="text"/>
    <p>
      <button>保存</button>
      <button @click="dialog=false">取消</button>
    </p>
  </div>
</template>

<script setup>
import {ref} from "vue";

const dataList = ref([{id: 1, name: "cc", age: 18, level_text: "SVIP", score: 1000}])
const dialog = ref(false)

function doEdit() {
  dialog.value = true
}
</script>

<style scoped>
.mask {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: black;
  opacity: 0.8;
  z-index: 998;
}

.dialog {
  position: fixed;
  top: 200px;
  right: 0;
  left: 0;
  width: 400px;
  height: 300px;
  background-color: white;
  margin: 0 auto;
  z-index: 9999;
}
</style>

后端

GET     http://127.0.0.1:8000/api/vip/          -> 会员列表
POST    http://127.0.0.1:8000/api/vip/          -> 新增会员(请求体中传入数据)
DELETE  http://127.0.0.1:8000/api/vip/会员ID/    -> 删除会员
PUT     http://127.0.0.1:8000/api/vip/会员ID/    -> 更新会员(请求体中传入数据)

urls.py

"""
from django.urls import path
from api.views import account
from api.views import vip

urlpatterns = [
    path('api/auth/', account.AuthView.as_view()),
    path('api/vip/', vip.VipView.as_view()),
    path('api/vip/<int:vid>/', vip.VipDetailView.as_view()),
]

models.py

from django.db import models

class UserInfo(models.Model):
    username = models.CharField(verbose_name="用户名", max_length=64)
    password = models.CharField(verbose_name="密码", max_length=64)
    token = models.CharField(verbose_name="token", max_length=64, null=True, blank=True)

class Vip(models.Model):
    """ 会员管理 """
    name = models.CharField(verbose_name="用户名", max_length=32)
    level = models.IntegerField(verbose_name="级别", choices=[(1, "VIP"), (2, "SVIP"), (3, "SSVIP")])
    score = models.IntegerField(verbose_name="积分")

views/vip.py

from rest_framework.views import APIView
from api import models
from rest_framework import serializers
from rest_framework.response import Response


class VipSerializers(serializers.ModelSerializer):
    level_text = serializers.CharField(source="get_level_display", read_only=True)

    class Meta:
        model = models.Vip
        fields = "__all__"


class VipView(APIView):
    def get(self, request):
        # 会员列表
        queryset = models.Vip.objects.all().order_by("id")
        ser = VipSerializers(instance=queryset, many=True)
        return Response({"code": 0, "data": ser.data})

    def post(self, request):
        # 新增
        pass


class VipDetailView(APIView):
    def delete(self, request, vid):
        # 删除
        pass

    def put(self, request, vid):
        # 修改
        pass

前端:VipView.vue

<template>
  <h1>会员管理</h1>
  <button @click="doEdit">编辑</button>
  <table border="1">
    <thead>
    <tr>
      <th>ID</th>
      <th>姓名</th>
      <th>级别</th>
      <th>积分</th>
      <th>操作</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="(item,idx) in dataList">
      <td>{{ item.id }}</td>
      <td>{{ item.name }}</td>
      <td>{{ item.level_text }}</td>
      <td>{{ item.score }}</td>
      <td>
        <a>编辑</a>
        |
        <a>删除</a>
      </td>
    </tr>
    </tbody>
  </table>

  <div v-show="dialog" class="mask"></div>
  <div v-show="dialog" class="dialog">
    <input type="text"/>
    <p>
      <button>保存</button>
      <button @click="dialog=false">取消</button>
    </p>
  </div>
</template>

<script setup>
import {ref, onMounted} from "vue";
import _axios from "@/plugins/axios.js";

const dataList = ref([{id: 1, name: "cc", age: 18, level_text: "SVIP", score: 1000}])
const dialog = ref(false)

onMounted(function (){
  _axios.get("/api/vip/").then((res) => {
    console.log(res.data)
    dataList.value = res.data.data
  })
})
function doEdit() {
  dialog.value = true
}
</script>

<style scoped>
.mask {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: black;
  opacity: 0.8;
  z-index: 998;
}

.dialog {
  position: fixed;
  top: 200px;
  right: 0;
  left: 0;
  width: 400px;
  height: 300px;
  background-color: white;
  margin: 0 auto;
  z-index: 9999;
}
</style>

删除

vip.py

from rest_framework.views import APIView
from api import models
from rest_framework import serializers
from rest_framework.response import Response


class VipSerializers(serializers.ModelSerializer):
    level_text = serializers.CharField(source="get_level_display", read_only=True)

    class Meta:
        model = models.Vip
        fields = "__all__"


class VipView(APIView):
    def get(self, request):
        # 会员列表
        queryset = models.Vip.objects.all().order_by("id")
        ser = VipSerializers(instance=queryset, many=True)
        return Response({"code": 0, "data": ser.data})

    def post(self, request):
        # 新增
        pass


class VipDetailView(APIView):
    def delete(self, request, vid):
        # 删除
        models.Vip.objects.filter(id=vid).delete()
        return Response({"code": 0})

    def put(self, request, vid):
        # 修改
        pass

cors.py

from django.utils.deprecation import MiddlewareMixin


class CorsMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        response['Access-Control-Allow-Origin'] = "*"
        response['Access-Control-Allow-Headers'] = "*"
        response['Access-Control-Allow-Methods'] = "*"
        return response

前端
VipView.vue

<template>
  <h1>会员管理</h1>
  <button @click="doEdit">新增</button>
  <table border="1">
    <thead>
    <tr>
      <th>ID</th>
      <th>姓名</th>
      <th>级别</th>
      <th>积分</th>
      <th>操作</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="(item,idx) in dataList">
      <td>{{ item.id }}</td>
      <td>{{ item.name }}</td>
      <td>{{ item.level_text }}</td>
      <td>{{ item.score }}</td>
      <td>
        <a>编辑</a>
        |
        <button @click="doDelete(item.id, idx)">删除</button>
      </td>
    </tr>
    </tbody>
  </table>

  <div v-show="dialog" class="mask"></div>
  <div v-show="dialog" class="dialog">
    <input type="text"/>
    <p>
      <button>保存</button>
      <button @click="dialog=false">取消</button>
    </p>
  </div>
</template>

<script setup>
import {ref, onMounted} from "vue";
import _axios from "@/plugins/axios.js";

const dataList = ref([{id: 1, name: "cc", age: 18, level_text: "SVIP", score: 1000}])
const dialog = ref(false)

onMounted(function () {
  _axios.get("/api/vip/").then((res) => {
    console.log(res.data)
    dataList.value = res.data.data
  })
})

function doEdit() {
  dialog.value = true
}

function doDelete(vid, idx) {
  _axios.delete(`/api/vip/${vid}/`).then((res) => {
    // console.log(res.data)
    if (res.data.code === 0) {
      dataList.value.splice(idx, 1)
    }
  })
}
</script>

<style scoped>
.mask {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: black;
  opacity: 0.8;
  z-index: 998;
}

.dialog {
  position: fixed;
  top: 200px;
  right: 0;
  left: 0;
  width: 400px;
  height: 300px;
  background-color: white;
  margin: 0 auto;
  z-index: 9999;
}
</style>

http://www.kler.cn/news/339320.html

相关文章:

  • Day47【最小生成树】
  • QT 优化登录框
  • C++ day03(作用域限定符、this、static、const)
  • 【Vue】Vue 快速教程
  • 多级代理与提权维权
  • 第Y2周:训练自己的数据集
  • ​​​​​​​如何使用Immersity AI将图片转换成3D效果视频
  • 如何通过视觉分析检测车辆逆行行为
  • 构建MySQL健康检查Web应用
  • Java-数据结构-Lambda表达式 (✪ω✪)
  • 深度图详解
  • 带隙基准Bandgap电路学习(一)
  • 职场上的人情世故,你知多少?这五点一定要了解
  • D31【python 接口自动化学习】- python基础之输入输出与文件操作
  • 五分钟极简带你快速入门若依框架实现二次开发
  • C++基础面试题 | C++中野指针和悬挂指针的区别?
  • paimon,基础查询语句测试
  • 力扣189.轮转数组
  • 如何录制微课教程?K12教育相关课程录制录屏软件推荐
  • 类与对象、封装、继承、多态