feat 添加商品的管理页面

This commit is contained in:
LittleBoy 2022-12-08 11:13:28 +08:00
parent 34483e80f7
commit 440824c98f
16 changed files with 300 additions and 10 deletions

View File

@ -4,6 +4,7 @@ import Login from '../views/Login.vue'
import NotFound from '../views/NotFound.vue'
import AdminLayout from '../views/layout/AdminLayout.vue'
import UserIndex from '../views/user/index.vue'
import GoodsIndex from '../views/goods/index.vue'
const routes: RouteRecordRaw[] = [
{
@ -13,11 +14,18 @@ const routes: RouteRecordRaw[] = [
children: [
{
path: 'home',
name: 'Home',
component: Home
},
{
path: 'user',
name: 'UserIndex',
component: UserIndex
},
{
path: 'goods',
name: 'GoodsIndex',
component: GoodsIndex
}
]
},

View File

@ -26,4 +26,22 @@ type UserInfoModel = {
status: number;
pointInfo: PointInfoModel;
parent?: UserInfoModel | null;
}
}
type GoodsModel = {
id?: number;
category?: number;
type?: number;
title?: string;
originPrice?: number;
price?: number;
stock?: number;
limitCount?: number;
cover?: string;
description?: string;
notice?: string;
onlineTime?: string;
offlineTime?: string;
createTime?: string;
updateTime?: string;
status?: number;
}

View File

@ -42,6 +42,17 @@ class Http {
return this.request<T>(url, data, 'get')
}
put<T>(url, data = null) {
return this.request<T>(url, data, 'put')
}
remove<T>(url, data = null) {
return this.request<T>(url, data, 'delete')
}
delete<T>(url, data = null) {
return this.request<T>(url, data, 'delete')
}
/**
* GET /xxxx?a=1&b=2
* NAME: value

View File

@ -0,0 +1,178 @@
<template>
<div>
<div class="search-form">
<span>标题<PInput v-model="param.title" placeholder="要查询的商品标题"/></span>
<span>
分类
<select v-model="param.category">
<option v-for="(text,value) in CategoryEnum" :key="value" :value="value">{{ text }}</option>
</select>
</span>
<button @click="onReset">重置</button>
<button @click="onSearch">搜索</button>
</div>
<table>
<tr>
<th>商品编号</th>
<th>标题</th>
<th>图片</th>
<th>分类</th>
<th>类型</th>
<th>原价</th>
<th>售卖价</th>
<th>库存</th>
<th>限购数量</th>
<th>上架时间</th>
<th>下架时间</th>
<th>状态</th>
<th>操作</th>
</tr>
<tr v-for="it in goodsList" :key="it.id">
<td>{{ it.id }}</td>
<td>{{ it.title }}</td>
<td><img :src="it.cover" style="width: 32px;height: 32px;"/></td>
<td>{{ CategoryEnum[it.category] || '未知' }}</td>
<td>{{ TypeEnum[it.type] || '未知' }}</td>
<td>{{ it.originPrice == 0 ? '-' : it.originPrice }}</td>
<td>{{ it.price }}</td>
<td>{{ it.stock }}</td>
<td>{{ it.limitCount }}</td>
<td>{{ it.onlineTime }}</td>
<td>{{ it.offlineTime }}</td>
<td>{{ StatusEnum[it.status] || '未知' }}</td>
<td>
<span @click="onEditData(it)">编辑</span>
<span>禁用</span>
<span @click="removeUser(it.id)">删除</span>
</td>
</tr>
</table>
<Pager :total="totalCount" show-refresh @refresh="loadDataList" @page-change="onPageChange"/>
</div>
<Modal v-model="modalVisible">
<div>
<div>
<span>昵称</span>
<p>
<PInput placeholder="请输入昵称" v-model="editData.nickname"/>
</p>
</div>
<div>
<span>省份</span>
<p>
<PInput placeholder="请输入省份" v-model="editData.province"/>
</p>
</div>
<div>
<span>城市</span>
<p>
<PInput placeholder="请输入城市" v-model="editData.city"/>
</p>
</div>
<button @click="updateData">提交</button>
</div>
</Modal>
</template>
<script setup lang="ts">
import {onMounted, reactive, ref} from "vue";
import http, {DataListModel} from "../../util/http";
import message from "../../components/message";
import Modal from "../../components/modal/modal.vue";
import Pager from "../../components/pager/Pager.vue";
//
//(1: 2: 3: 4:)
const CategoryEnum = {
1: '普通',
2: '精选',
3: '秒杀',
4: '抽奖',
}
//(1: 2:)
const TypeEnum = {
1: '实物',
2: '虚拟'
}
const StatusEnum = {
1: '正常',
2: '禁用',
0: '已删除'
}
const param = reactive({
title: null,
category: null,
page: 1,
pageSize: 10
})
const modalVisible = ref(false)
const goodsList = ref<GoodsModel[]>([]);
const editData = reactive<GoodsModel>({
id: 0
});
const totalCount = ref(0)
function onPageChange(currentPage: number) {
param.page = currentPage;
loadDataList();
}
function onReset() {
param.page = 1;
param.title = null;
param.category = null
loadDataList();
}
function onSearch() {
param.page = 1;
loadDataList();
}
function loadDataList() {
http.post<DataListModel<GoodsModel>>('/admin/goods/list', param).then(res => {
goodsList.value = res.items
totalCount.value = res.total
})
}
function onEditData(data: GoodsModel) {
modalVisible.value = true
}
async function updateData() {
try {
await http.put(`/admin/goods/${editData.id}`, editData)
modalVisible.value = false;
message.toast('更新成功');
loadDataList();
} catch (e) {
message.toast(e.message || '更新失败')
}
}
/**
* 删除用户
* @param id 要删除的用户id
*/
async function removeUser(id: number) {
if (!confirm('是否删除?')) {
return;
}
try {
await http.delete(`/admin/goods/${id}`);
message.toast('删除成功');
loadDataList();
} catch (e) {
message.toast(e.message || '删除失败')
}
}
onMounted(loadDataList)
</script>
<style scoped>
</style>

View File

@ -13,6 +13,7 @@
<div class="title">积分管理系统</div>
<div class="menu-list">
<router-link active-class="active-menu" to="/home">HOME</router-link>
<router-link active-class="active-menu" to="/goods">商品管理</router-link>
<router-link active-class="active-menu" to="/user">用户管理</router-link>
</div>
</div>

View File

@ -1,14 +1,15 @@
package me.xiaoyan.point.api.controller.admin;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import me.xiaoyan.point.api.error.BizException;
import me.xiaoyan.point.api.pojo.Goods;
import me.xiaoyan.point.api.pojo.vo.GoodsQueryParam;
import me.xiaoyan.point.api.pojo.vo.PageDataResult;
import me.xiaoyan.point.api.pojo.vo.PageParam;
import me.xiaoyan.point.api.service.GoodsService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import me.xiaoyan.point.api.util.DataStatus;
import org.apache.ibatis.annotations.Delete;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -22,4 +23,43 @@ public class GoodsAdminController {
public PageDataResult list(@RequestBody GoodsQueryParam param) {
return PageDataResult.convert(goodsService.queryByPage(param));
}
// 新增
@PostMapping
public Goods create(@RequestBody Goods goods) {
if (!goodsService.save(goods)) {
throw BizException.saveFail();
}
return goods;
}
// 修改
@PutMapping("/{id}")
public Goods update(@RequestBody Goods goods, @PathVariable("id") long id) {
goods.setId(id);
if (!goodsService.updateById(goods)) {
throw BizException.saveFail();
}
return goods;
}
// 查询
@GetMapping("/{id}")
public Goods get(@PathVariable("id") long id) {
return goodsService.getById(id);
}
// 删除
@DeleteMapping("/{id}")
public boolean remove(@PathVariable("id") long id) {
if (id < 1) throw BizException.paramError();
// 只是逻辑删除 -> 将状态更新未删除即可
return goodsService.updateById(
Goods.builder()
.id(id)
.status(DataStatus.DELETE) // 状态设置为删除
.build()
);
}
}

View File

@ -17,11 +17,20 @@ public class BizException extends RuntimeException {
public static BizException create(String message) {
return new BizException(-1, message);
}
public static BizException create(int code,String message) {
public static BizException create(int code, String message) {
return new BizException(code, message);
}
public static BizException saveFail() {
return create(1022,"保存失败");
return create(1022, "保存失败");
}
public static BizException paramError(String message) {
return create(1201, message);
}
public static BizException paramError() {
return paramError("请求参数不正确");
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -83,21 +84,25 @@ public class Goods implements Serializable {
/**
* 上架时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date onlineTime;
/**
* 下架时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date offlineTime;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**

View File

@ -5,6 +5,7 @@ import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -39,9 +40,11 @@ public class OrderInfo {
private Integer uid;
//订单数据
private String data;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
//订单状态(0:已删除 1:已取消 2:待确认 3:已完成)
private Integer status;

View File

@ -2,6 +2,7 @@ package me.xiaoyan.point.api.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -22,6 +23,7 @@ public class Point implements Serializable {
private Integer totalPoint;
private Integer validPoint;
private Integer expirePoint;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;
private Date updateTime;
}

View File

@ -3,6 +3,7 @@ package me.xiaoyan.point.api.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -25,6 +26,8 @@ public class PointRecord implements Serializable {
private Integer point;
private Integer currentTotalPoint;
private String reason;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;
}

View File

@ -2,6 +2,7 @@ package me.xiaoyan.point.api.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -22,5 +23,7 @@ public class SignRecord implements Serializable {
private Integer uid;
private Integer point;
private String ip;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -58,6 +59,7 @@ public class UserInfo implements Serializable {
/**
* 第一次登录时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date firstLoginTime;
private Date updateTime;
/**

View File

@ -5,5 +5,5 @@ import lombok.Data;
@Data
public class GoodsQueryParam extends PageParam {
private String title;
private int category;
private Integer category;
}

View File

@ -7,6 +7,7 @@ import me.xiaoyan.point.api.pojo.Goods;
import me.xiaoyan.point.api.pojo.vo.GoodsQueryParam;
import me.xiaoyan.point.api.service.GoodsService;
import me.xiaoyan.point.api.mapper.GoodsMapper;
import me.xiaoyan.point.api.util.DataStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -31,6 +32,11 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
if (StringUtils.hasText(param.getTitle())) {
q.eq("title", param.getTitle().trim());
}
if(param.getCategory() != null){
q.eq("category", param.getCategory());
}
// 不查询删除状态数据
q.ne("status", DataStatus.DELETE);
return getBaseMapper().selectPage(param.getPage(), q);
}

View File

@ -2,6 +2,7 @@ package me.xiaoyan.point.api.util;
public class DataStatus {
public static final int NORMAL = 1;
public static final int DISABLED = 2;
public static final int DELETE = 0;
}