这里写目录标题
一级目录
二级目录
三级目录
虚拟机安装Vmware
安装虚拟机14-15
VMware Workstation Pro 15.5.6
Vt-x问题
解决问题:开机-F2(F1-ESC-F8)----CPU设置–VT-X(虚拟化技术) 设置为启动即可 F8保存
1.找班里同学 帮助设置
2.找项目经理
检查网卡
如果没有网卡就重新安装vmware
注意⚠️:可以没有vmnet1但是必须有vmnet8
运行Linux系统
用户名和密码: root/root
mybatisplus代码生成器
说明:代码生成器当你输入模版和数据库表会自动生成controller和service和mapper层架构代码具体详情可以到该网站进行查看;
商品分类参数实现
2.1 商品分类参数说明
1).动态参数
2).静态属性
商品分类参表设计
实现商品分类参数页面跳转
商品分类参数前端代码
<template>
<div>
<!-- 定义面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>商品分类参数</el-breadcrumb-item>
</el-breadcrumb>
<!-- 定义卡片视图 -->
<el-card class="box-card">
<!-- 1.定义头部警告区域 不可以被关闭-->
<el-alert title="注意: 只允许为三级商品分类设定参数" type="warning" show-icon center :closable="false"></el-alert>
<!-- 2.定义商品分类选择区域 -->
<el-row>
<el-col>
<p>
<strong>
选择商品分类:
<!-- 定义级联选择器,获取商品分类信息-->
<!-- 数据说明: options="数据的来源" props:定义级联选择器父子关系信息 -->
<el-cascader v-model="itemCatIds" :options="itemCatList" :props="props" clearable @change="handleChange">
</el-cascader>
</strong>
</p>
</el-col>
</el-row>
<!-- 定义tabs 标签页 activeName被激活的页签 -->
<el-tabs v-model="activeName" @tab-click="handleClick">
<!--定义动态参数的按钮 -->
<el-tab-pane label="动态参数" name="dynamic">
<!-- 定义添加参数按钮-->
<el-button type="primary" size="mini" :disabled="isDisableBtn" @click="addDialogVisible = true">添加动态参数
</el-button>
<!-- 动态参数表格-->
<el-table :data="dynamicTableData" stripe border>
<el-table-column type="expand">
<template slot-scope="scope">
<!-- 循环遍历展现数据-->
<el-tag v-for="(paramVal,index) in scope.row.paramVals" :key="index" closable @close="closeTag(scope.row,index)">{{paramVal}}</el-tag>
<!-- 添加新增tag标签框-->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue"
ref="saveDynamicTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)">
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag
</el-button>
</template>
</el-table-column>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="paramName" label="参数名称"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini" @click="updateItemCatParamBtn(scope.row)">编辑
</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteItemCatParamBtn(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!--定义静态属性的按钮 -->
<el-tab-pane label="静态属性" name="static">
<!-- 定义添加参数按钮-->
<el-button type="primary" size="mini" :disabled="isDisableBtn" @click="addDialogVisible = true">添加静态属性
</el-button>
<!-- 定义静态属性表格-->
<el-table :data="staticTableData" stripe border>
<el-table-column type="expand">
<template slot-scope="scope">
<!-- 循环遍历展现数据-->
<el-tag v-for="(paramVal,index) in scope.row.paramVals" :key="index" closable @close="closeTag(scope.row,index)">{{paramVal}}</el-tag>
<!-- 添加新增tag标签框-->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue"
ref="saveDynamicTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)"
@blur="handleInputConfirm(scope.row)">
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag
</el-button>
</template>
</el-table-column>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="paramName" label="属性名称"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini" @click="updateItemCatParamBtn(scope.row)">编辑
</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteItemCatParamBtn(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</el-card>
<!-- 定义新增参数对话框 -->
<el-dialog :title="'添加' + getTitleName" :visible.sync="addDialogVisible" width="50%" @close="closeDialog">
<!-- 添加参数对form表单提交 -->
<el-form :model="addItemCatParam" :rules="itemCatParamRules" ref="addItemCatParamRef" label-width="100px"
class="demo-ruleForm">
<el-form-item :label="getTitleName" prop="paramName">
<el-input v-model="addItemCatParam.paramName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addItemCatParamBtn">确 定</el-button>
</span>
</el-dialog>
<!-- 定义修改参数对话框 -->
<el-dialog :title="'修改' + getTitleName" :visible.sync="updateDialogVisible" width="50%" @close="closeUpdateDialog">
<!-- 修改参数对form表单提交 -->
<el-form :model="updateItemCatParam" :rules="itemCatParamRules" ref="updateItemCatParamRef" label-width="100px">
<el-form-item :label="getTitleName" prop="paramName">
<el-input v-model="updateItemCatParam.paramName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="updateDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="updateItemCatParamSubmit">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
//1.定义初始化函数
created() {
//获取所有的商品分类信息
this.getItemCatList()
},
data() {
return {
itemCatList: [],
//定义级联选择器属性
props: {
expandTrigger: 'hover',
value: "id", //定义选中的值
label: "name", //定义展现的值
children: "children" //定义子级信息
},
//定义商品分类ID
itemCatIds: [],
//默认激活的页面名称
activeName: "dynamic",
//定义动态参数
dynamicTableData: [],
//定义静态属性
staticTableData: [],
//控制对话框显示
addDialogVisible: false,
//定义新增商品参数的form对象
addItemCatParam: {
//定义商品分类ID
itemCatId: '',
paramName: '',
paramType: 1
},
updateItemCatParam: {
paramId: '',
paramName: ''
},
//定义商品分类参数校验规则
itemCatParamRules: {
paramName: [{
required: true,
message: '请输参数名称',
trigger: 'blur'
}]
},
//定义修改对话框的开关
updateDialogVisible: false
}
},
methods: {
//获取所有商品分类信息
async getItemCatList() {
const {
data: result
} = await this.$http.get("/itemCat/findItemCatList/3")
if (result.status !== 200) return this.$message.error("商品分类查询失败")
this.itemCatList = result.data
//console.log(this.itemCatList)
},
//当级联选择器发生变化时 触发事件 获取数据
handleChange() {
this.getItemCatParam()
},
handleClick() {
//默认点击事件
this.getItemCatParam()
},
async getItemCatParam() {
//console.log(this.itemCatIds)
//如果商品分类不是3级时,需要直接返回 将数组清空
if (this.itemCatIds.length !== 3) {
this.itemCatIds = []
this.dynamicTableData = []
this.staticTableData = []
return
}
//将字符串名称转化为 type类型
let itemCatId = this.itemCatIds[2]
let paramType = this.activeName === "dynamic" ? 1 : 2
//根据itemCatId 获取对应的商品分类参数数据
let {
data: result
} = await this.$http.get("/itemCatParam/findItemCatParamListByType", {
params: {
itemCatId: itemCatId,
paramType: paramType
}
})
if (result.status !== 200) return this.$message.error("获取商品分类参数失败")
//为了展现商品参数tab页 则利用,号分割参数 val1,val2,val3,val4 最好判断数据是否有效
for (let itemCatParam of result.data) {
itemCatParam.paramVals = itemCatParam.paramVals ? itemCatParam.paramVals.split(",") : [],
//设定input框是否显示
itemCatParam.inputVisible = false
//定义用户输入的内容
itemCatParam.inputValue = ''
}
//获取数据之后根据参数类型赋值
if (paramType === 1) {
this.dynamicTableData = result.data
} else {
this.staticTableData = result.data
}
},
//当关闭添加对话框时重置表格数据
closeDialog() {
this.$refs.addItemCatParamRef.resetFields()
},
//添加商品分类参数信息
addItemCatParamBtn() {
//完成用户数据校验
this.$refs.addItemCatParamRef.validate(async (valid) => {
if (valid) {
this.addItemCatParam.itemCatId = this.getItemCatId()
this.addItemCatParam.paramType = this.getParamType()
//发起post请求,实现商品分类参数新增
let {
data: result
} = await this.$http.post("/itemCatParam/addItemCatParam", this.addItemCatParam)
if (result.status !== 200) {
return this.$message.error("商品分类参数新增失败")
}
this.$message.success("商品分类参数提交成功")
//重新加载商品分类参数列表
this.getItemCatParam()
//关闭对话框
this.addDialogVisible = false
} else {
return false;
}
})
},
//获取商品分类信息
getItemCatId() {
if (this.itemCatIds.length === 3) {
return this.itemCatIds[2]
}
return null
},
getParamType() {
return this.activeName === "dynamic" ? 1 : 2
},
//点击更新按钮 实现数据封装
updateItemCatParamBtn(itemCatParam) {
this.updateItemCatParam.paramId = itemCatParam.paramId
this.updateItemCatParam.paramName = itemCatParam.paramName
//展现修改对话框
this.updateDialogVisible = true
},
//实现商品分类参数更新操作
updateItemCatParamSubmit() {
//完成用户数据校验
this.$refs.updateItemCatParamRef.validate(async (valid) => {
if (valid) {
//发起put请求,实现商品分类参数新增
let {
data: result
} = await this.$http.put("/itemCatParam/updateItemCatParam", this.updateItemCatParam)
if (result.status !== 200) {
return this.$message.error("商品分类参数修改失败")
}
this.$message.success("商品分类参数修改成功")
//重新加载商品分类参数列表
this.getItemCatParam()
//关闭对话框
this.updateDialogVisible = false
} else {
return false;
}
})
},
closeUpdateDialog() {
this.$refs.updateItemCatParamRef.resetFields()
},
//实现商品删除操作
async deleteItemCatParamBtn(itemCatParam) {
let confirmResult = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(error => error)
if (confirmResult !== "confirm") return this.$message.info("删除操作取消")
//请求路径:/itemCatParam/deleteItemCatParamById
let {
data: result
} = await this.$http.delete("/itemCatParam/deleteItemCatParamById", {
params: {
paramId: itemCatParam.paramId
}
})
if (result.status !== 200) return this.$message.error("删除操作失败")
this.$message.success("删除操作成功")
//重新加载数据
this.getItemCatParam()
},
handleInputConfirm(itemCatParam) {
//确认用户输入的内容是有效的
if(itemCatParam.inputValue.trim().length === 0 ){
//重置数据
itemCatParam.inputValue = ''
itemCatParam.inputVisible = false
//停止程序执行
return
}
//如果用户数据不为null 则进行数据更新操作
itemCatParam.paramVals.push(itemCatParam.inputValue)
//更新商品分类参数
this.updateItemCatParamArgs(itemCatParam)
},
showInput(itemCatParam) {
itemCatParam.inputVisible = true
//点击input框之后,自动获取焦点 当页面上元素被重新渲染之后 才可以执行
this.$nextTick(_ => {
this.$refs.saveDynamicTagInput.$refs.input.focus();
})
},
closeTag(itemCatParam,index){
//删除数组中指定的数据
itemCatParam.paramVals.splice(index,1)
//之后将数据保存即可
this.updateItemCatParamArgs(itemCatParam)
},
async updateItemCatParamArgs(itemCatParam){
itemCatParam.inputValue = ''
itemCatParam.inputVisible = false
let strVals = itemCatParam.paramVals.join(",")
let paramId = itemCatParam.paramId
//更新商品分类参数
let {data: result} = await this.$http.put("/itemCatParam/updateItemCatParam",{paramId:paramId,paramVals:strVals})
if(result.status !== 200) return this.$message.error("商品分类参数更新失败")
this.$message.success("商品分类参数更新成功")
}
},
computed: {
//如果禁用返回true,否则返回false
isDisableBtn() {
if (this.itemCatIds.length !== 3)
return true
return false
},
getTitleName() {
return this.activeName === "dynamic" ? "动态参数" : "静态属性"
}
}
}
</script>
<style lang="less" scoped>
/* elementUI中的标签 在被渲染为html之后 变成 class的类型 */
.el-tag{
margin-right: 10px;
}
.el-cascader {
width: 30%;
}
.input-new-tag {
width: 200px;
}
</style>
商品分类参数业务实现
表头的内容
<!-- 1.定义头部警告区域 不可以被关闭 type:表示字体的颜色,show-icon:表示字体的位置,:closable是否可以关闭该表头 false:不可以被关闭,true :表示可以关闭-->
<el-alert title="注意: 只允许为三级商品分类设定参数" type="warning" show-icon center :closable="false"></el-alert>
实现商品分类参数列表
页面HTML
<!-- 2.定义商品分类选择区域 -->
<el-row>
<el-col>
<p>
<strong> //加粗的效果
选择商品分类:
<!-- 定义级联选择器,获取商品分类信息-->
<!-- 数据说明: options="数据的来源" props:定义级联选择器父子关系信息clearable是否可以被清空-->
<el-cascader v-model="itemCatIds" :options="itemCatList" :props="props" clearable @change="handleChange">
</el-cascader>
</strong>
</p>
</el-col>
</el-row>
页面JS
效果展现
商品分类参数接口文档
编辑pojo类
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author
* 时间 2021/3/31
*/
//定义商品分类参数
@TableName("item_cat_param")
@Data
@Accessors(chain = true)
public class ItemCatParam extends BasePojo{
@TableId(type = IdType.AUTO)
private Integer paramId; //分类参数ID
private String paramName; //分类参数名称
private Integer itemCatId; //商品分类id
private Integer paramType; //参数类型 1动态参数 2.静态属性
private String paramVals; //参数值
}
mapper代码
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.ItemCatParam;
public interface ItemCatParamMapper extends BaseMapper<ItemCatParam> {
}
编辑ItemCatParamController
package com.jt.controller;
import com.jt.pojo.ItemCatParam;
import com.jt.service.ItemCatParamService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping("/itemCatParam")
public class ItemCatParamController {
@Autowired
private ItemCatParamService itemCatParamService;
/**
* 实现商品分类参数的查询
* URL: /itemCatParam/findItemCatParamListByType?itemCatId=564¶mType=1
* 参数: itemCatId,paramType
* 返回值: SysResult对象
*/
@GetMapping("findItemCatParamListByType")
public SysResult findItemCatParamListByType(ItemCatParam itemCatParam){
List<ItemCatParam> paramList =
itemCatParamService.findParamListByType(itemCatParam);
return SysResult.success(paramList);
}
}
编辑ItemCatParamService
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatParamMapper;
import com.jt.pojo.ItemCatParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ItemCatParamServiceImpl implements ItemCatParamService{
@Autowired
private ItemCatParamMapper itemCatParamMapper;
//Sql:select * from item_cat_param where item_cat_id = xxx and param_type=1
@Override //参数中只有2个数据不为null
public List<ItemCatParam> findParamListByType(ItemCatParam itemCatParam) {
//如果有主键当作已知条件则根据id进行查询,已知条件中没有主键可以根据对象进行查询
//QueryWrapper<ItemCatParam> queryWrapper = new QueryWrapper<>(itemCatParam);
return itemCatParamMapper.selectList(new QueryWrapper<>(itemCatParam));
}
}
页面效果展现
商品分类参数新增
页面分析
1).页面添加按钮
<!-- 定义添加参数按钮-->
<el-button type="primary" size="mini" :disabled="isDisableBtn" @click="addDialogVisible = true">添加动态参数
</el-button>
对话框窗口
3).页面JS
业务接口
编辑ItemCatParamController
package com.jt.controller;
import com.jt.pojo.ItemCatParam;
import com.jt.service.ItemCatParamService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping("/itemCatParam")
public class ItemCatParamController {
@Autowired
private ItemCatParamService itemCatParamService;
/**
* 实现商品分类参数的查询
* URL: /itemCatParam/findItemCatParamListByType?itemCatId=564¶mType=1
* 参数: itemCatId,paramType
* 返回值: SysResult对象
*/
@GetMapping("/findItemCatParamListByType")
public SysResult findItemCatParamListByType(ItemCatParam itemCatParam){
List<ItemCatParam> paramList =
itemCatParamService.findParamListByType(itemCatParam);
return SysResult.success(paramList);
}
/**
* 实现商品分类新增操作
* URL: /itemCatParam/addItemCatParam
* 参数: itemCatParam接收 注解格式要求
* 返回值: SysResult对象
*/
@PostMapping("/addItemCatParam")
public SysResult addItemCatParam(@RequestBody ItemCatParam itemCatParam){
itemCatParamService.addItemCatParam(itemCatParam);
return SysResult.success();
}
编辑ItemCatParamService
接口代码
package com.jt.service;
import com.jt.pojo.ItemCatParam;
import java.util.List;
public interface ItemCatParamService {
List<ItemCatParam> findParamListByType(ItemCatParam itemCatParam);
void addItemCatParam(ItemCatParam itemCatParam);
}
实现类代码
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatParamMapper;
import com.jt.pojo.ItemCatParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ItemCatParamServiceImpl implements ItemCatParamService{
@Autowired
private ItemCatParamMapper itemCatParamMapper;
//Sql:select * from item_cat_param where item_cat_id = xxx and param_type=1
@Override //参数中只有2个数据不为null
public List<ItemCatParam> findParamListByType(ItemCatParam itemCatParam) {
//QueryWrapper<ItemCatParam> queryWrapper = new QueryWrapper<>(itemCatParam);
return itemCatParamMapper.selectList(new QueryWrapper<>(itemCatParam));
}
@Override
@Transactional //事务控制
public void addItemCatParam(ItemCatParam itemCatParam) {
itemCatParamMapper.insert(itemCatParam);
}
}
商品分类参数的修改
数据的修改和参数的修改为一个url地址
页面分析
ItemCatParamController
package com.jt.controller;
import com.jt.pojo.ItemCatParam;
import com.jt.service.ItemCatParamService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping("/itemCatParam")
public class ItemCatParamController {
@Autowired
private ItemCatParamService itemCatParamService;
/**
* 实现商品分类参数的查询
* URL: /itemCatParam/findItemCatParamListByType?itemCatId=564¶mType=1
* 参数: itemCatId,paramType
* 返回值: SysResult对象
*/
@GetMapping("/findItemCatParamListByType")
public SysResult findItemCatParamListByType(ItemCatParam itemCatParam){
List<ItemCatParam> paramList =
itemCatParamService.findParamListByType(itemCatParam);
return SysResult.success(paramList);
}
/**
* 实现商品分类新增操作
* URL: /itemCatParam/addItemCatParam
* 参数: itemCatParam接收 注解格式要求
* 返回值: SysResult对象
*/
@PostMapping("/addItemCatParam")
public SysResult addItemCatParam(@RequestBody ItemCatParam itemCatParam){
itemCatParamService.addItemCatParam(itemCatParam);
return SysResult.success();
}
/**
* 实现商品分类参数的更新
* URL: /itemCatParam/updateItemCatParam
* 参数: ItemCatParam参数
* 返回值: SysResult对象
*/
@PutMapping("/updateItemCatParam")
public SysResult updateItemCatParam(@RequestBody ItemCatParam itemCatParam){
itemCatParamService.updateItemCatParam(itemCatParam);
return SysResult.success();
}
}
编辑ItemCatParamService
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatParamMapper;
import com.jt.pojo.ItemCatParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ItemCatParamServiceImpl implements ItemCatParamService{
@Autowired
private ItemCatParamMapper itemCatParamMapper;
//Sql:select * from item_cat_param where item_cat_id = xxx and param_type=1
@Override //参数中只有2个数据不为null
public List<ItemCatParam> findParamListByType(ItemCatParam itemCatParam) {
//QueryWrapper<ItemCatParam> queryWrapper = new QueryWrapper<>(itemCatParam);
return itemCatParamMapper.selectList(new QueryWrapper<>(itemCatParam));
}
@Override
@Transactional //事务控制
public void addItemCatParam(ItemCatParam itemCatParam) {
itemCatParamMapper.insert(itemCatParam);
}
@Override
@Transactional
public void updateItemCatParam(ItemCatParam itemCatParam) {
itemCatParamMapper.updateById(itemCatParam);//因为已知条件有主键所以可以使用byid进行操作
}
}
填充(间距):
margin:则是方框与方框之间的间距
border:则是外放框与内方框的间距;
padding:则是内方框与最里层的间距(多数为数据)
在element中标签在被渲染完了之后变成了class类型
效果展现
商品业务实现(商品列表)
实现页面跳转
商品数据结构分析
POJO对象
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author
* 时间 2021/4/7
*/
@TableName("item")
@Data
@Accessors(chain = true)
public class Item extends BasePojo{
@TableId(type = IdType.AUTO)
private Integer id; //商品Id号
private String title; //商品标题信息
private String sellPoint; //卖点信息
private Integer price; //商品价格 一般采用整数避免小数的精度问题 9.98
private Integer num; //商品数量
private String images; //商品图片 1.jpg,2.jpg
private Integer itemCatId; //商品分类ID号
private Boolean status; //状态信息 0 下架 1 上架
}
2.表结构
商品列表展现
页面结构
业务接口
编辑ItemController
@RestController
@CrossOrigin
@RequestMapping("/item")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 实现商品列表展现
* URL: /item/getItemList?query=&pageNum=1&pageSize=10
* 参数: 使用分页参数
* 返回值: SysResult对象(pageResult对象)
*/
@GetMapping("/getItemList")
public SysResult findItemList(PageResult pageResult){
//查询分页数据 返回分页对象
pageResult = itemService.findItemList(pageResult);
return SysResult.success(pageResult);
}
}
编辑ItemService
@Service
public class ItemServiceImpl implements ItemService{
@Autowired
private ItemMapper itemMapper;
/**
* 1.使用分页查询
* 1.1手写sql
* 1.2利用MP
* @param pageResult
* @return
*/
@Override
public PageResult findItemList(PageResult pageResult) {
IPage page = new Page(pageResult.getPageNum(),
pageResult.getPageSize());
QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
//用户是否传递参数
boolean flag = StringUtils.hasLength(pageResult.getQuery());
queryWrapper.like(flag,"title", pageResult.getQuery());
//上面传回来的是三个参数,但是实际需要传回来五个参数
//分页对象,分页的条件
page = itemMapper.selectPage(page,queryWrapper);
long total = page.getTotal();//获取总数
List<Item> itemList = page.getRecords();//分页后的结果
return pageResult.setTotal(total).setRows(itemList);
}
}
页面效果展现
添加过滤器
说明:将价格进行格式化,由于在数据库中不存在小数点,但是需要在页面中展现小数点,在每个价格都要除以100,此时就要使用过滤器
说明: 在main.js中添加过滤器.
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
import './assets/css/global.css'
import './assets/ali-icon/iconfont.css'
/* 导入axios包 */
import axios from 'axios'
/* 设定axios的请求根目录 */
axios.defaults.baseURL = 'http://localhost:8091/'
/* 向vue对象中添加全局对象 以后发送ajax请求使用$http对象 */
Vue.prototype.$http = axios
//定义格式化价格的过滤器
Vue.filter('priceFormat',(price) => {
return (price/100).toFixed(2)//将结果除以100,并且保留两位小数;
})
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
商品状态修改
页面JS分析
1).页面JS
2).页面ajax请求
编辑ItemController
package com.jt.controller;
import com.jt.pojo.Item;
import com.jt.service.ItemService;
import com.jt.vo.ItemVO;
import com.jt.vo.PageResult;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping("/item")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 实现商品列表展现
* URL: /item/getItemList?query=&pageNum=1&pageSize=10
* 参数: 使用分页参数
* 返回值: SysResult对象(pageResult对象)
*/
@GetMapping("/getItemList")
public SysResult findItemList(PageResult pageResult){
//查询分页数据 返回分页对象
pageResult = itemService.findItemList(pageResult);
return SysResult.success(pageResult);
}
/**
* url地址: /item/updateItemStatus
* 请求参数: 利用Item对象接收
* id: item.id,
* status: item.status
* 返回值: SysResult对象
*/
@PutMapping("/updateItemStatus")
public SysResult updateItemStatus(@RequestBody Item item){
itemService.updateItemStatus(item);
return SysResult.success();
}
}
编辑ItemService
商品删除自己实现
商品新增页面跳转
跳转新增页面
1.点击按钮发送请求
2.编辑导航路由
<template>
<div>
<!-- 定义面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>商品新增</el-breadcrumb-item>
</el-breadcrumb>
<!-- 定义卡片视图 -->
<el-card class="box-card">
<!-- 定义页面提示信息 -->
<el-alert title="新增商品流程" type="info" effect="dark" center show-icon :closable="false"></el-alert>
<!-- 定义步骤条 字符串需要转化为数值 -->
<el-steps :active="activeIndex - 0" finish-status="success" align-center>
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- 定义标签页 before-leave:切换标签之前的钩子,若返回 false 或者返回 Promise 且被 reject,则阻止切换。 -->
<el-form :model="addItemForm" :rules="addItemFormRules" ref="addItemFormRef" label-width="100px"
label-position="top">
<el-tabs v-model="activeIndex" :tab-position="'left'" :before-leave="beforeLeave" @tab-click="tabClick">
<el-tab-pane label="基本信息" name="0">
<el-form-item label="商品标题" prop="title">
<el-input v-model="addItemForm.title"></el-input>
</el-form-item>
<el-form-item label="商品卖点" prop="sellPoint">
<el-input v-model="addItemForm.sellPoint"></el-input>
</el-form-item>
<el-form-item label="商品价格" prop="price">
<el-input v-model="addItemForm.price" type="number"></el-input>
</el-form-item>
<el-form-item label="商品数量" prop="num">
<el-input v-model="addItemForm.num" type="number"></el-input>
</el-form-item>
<el-form-item label="商品分类信息" prop="price">
<!-- 通过级联获取商品分类信息-->
<el-cascader v-model="itemCatIds" :options="itemCatList" :props="props" @change="changeCascader">
</el-cascader>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品参数" name="1">
<el-form-item :label="item.paramName" v-for="item in dynamicTableData" :key="item.paramId">
<!-- 通过复选框展现商品分类参数信息-->
<el-checkbox-group v-model="item.paramVals">
<el-checkbox :label="param" v-for="(param,index) in item.paramVals" :key="index" border></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-tab-pane>
<!-- 渲染商品分类静态属性数据 -->
<el-tab-pane label="商品属性" name="2">
<el-form-item :label="item.paramName" v-for="item in staticTableData" :key="item.paramId">
<el-input v-model="item.paramVals"></el-input>
</el-form-item>
</el-tab-pane>
<!-- 实现图片上传 multiple支持多选文件 -->
<el-tab-pane label="商品图片" name="3">
<!--
class="upload-demo" 图片上传的类型
:action="uploadUrl" 必选参数,上传的地址
:on-preview="handlePreview" 当上传图片之后预览的回调
:on-remove 删除图片的回调函数
:on-success 上传成功的回调
list-type="picture" 上传文件的类型 只允许上传图片
multiple 是否支持多选文件
drag 是否允许拖拽
name 请求的参数名称: file
-->
<el-upload class="upload-demo" :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove"
:on-success="handleSuccess" list-type="picture" multiple drag>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
</el-tab-pane>
<el-tab-pane label="商品详情" name="4">
<!-- 定义富文本编辑器-->
<quill-editor ref="myQuillEditor" v-model="itemDesc.itemDesc">
</quill-editor>
<!-- 定义添加商品按钮-->
<el-button type="primary" class="addItemBtnClass" @click="addItemBtn">添加商品</el-button>
</el-tab-pane>
</el-tabs>
</el-form>
</el-card>
<!-- 定义图片展现对话框 -->
<el-dialog title="图片预览" :visible.sync="dialogImageVisible">
<img :src="imageUrlPath" width="100%" height="100%" />
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
activeIndex: '0',
addItemForm: {
title: '',
sellPoint: '',
price: 0,
num: 0,
itemCatId: '',
images: []
//itemDesc: '',
//dynamicArgs: [],
//staticArgs: []
},
itemDesc: {
itemDesc: ""
},
itemParam: {
dynamicArray: [],
staticArray: [],
dynamicArgs: "",
staticArgs: ""
}
,
addItemFormRules: {
title: [{
required: true,
message: '请输入商品标题信息',
trigger: 'blur'
}],
sellPoint: [{
required: true,
message: '请输入商品卖点信息',
trigger: 'blur'
}],
price: [{
required: true,
message: '请输入商品价格信息',
trigger: 'blur'
}],
num: [{
required: true,
message: '请输入商品数量信息',
trigger: 'blur'
}],
},
itemCatIds: [],
itemCatList: [],
props: {
expandTrigger: 'hover',
value: "id", //选中数据的value值
label: "name", //选中数据展现名称
children: "children", //自选项数据
},
//设置商品动态参数
dynamicTableData: [],
staticTableData: [],
//定义文件上传路径地址
//uploadUrl: "http://localhost:8091/file/upload",
uploadUrl: "http://manage.jt.com/file/upload",
//定义图片网络访问地址
imageUrlPath: "",
//定义图片控制开关
dialogImageVisible: false
}
},
created() {
this.findItemCatList()
},
methods: {
//1.获取所有商品分类信息
async findItemCatList() {
const {
data: result } = await this.$http.get("/itemCat/findItemCatList/3")
if (result.status !== 200) return this.$message.error("查询商品分类信息失败")
this.itemCatList = result.data
},
//修改商品分类选项
changeCascader() {
this.addItemForm.itemCatId = this.itemCatIds[2]
//console.log(this.addItemForm.itemCatId)
},
//当标签页数据没有完成选择时 不让切换标签页
beforeLeave(activeName, oldActiveName) {
//console.log(this.itemCatIds.length)
//console.log(typeof(oldActiveName))
//注意oldActiveName的数据类型为字符串
if (this.itemCatIds.length !== 3 && oldActiveName === '0') {
this.$message.error("请先选择商品分类")
return false
}
},
async tabClick() {
//1.判断索引下标值是否为1 商品参数
if (this.activeIndex === '1') {
//发起Ajax请求 获取商品分类的参数信息
//http://localhost:8091/itemCatParam/findItemCatParamListByType?paramType=1&itemCatId=3
let itemCatId = this.addItemForm.itemCatId
//动态属性
let type = 1
let {
data: result
} = await this.$http.get("/itemCatParam/findItemCatParamListByType", {
params: {
paramType: type,
itemCatId: itemCatId
}
})
if (result.status !== 200) return this.$message.error("商品分类参数查询失败")
//查询完成之后赋值给动态参数对象
//将商品分类参数中的vals转化为数组
for (let itemCatParam of result.data) {
itemCatParam.paramVals = itemCatParam.paramVals ? itemCatParam.paramVals.split(",") : []
}
this.dynamicTableData = result.data
}
if (this.activeIndex === '2') {
let itemCatId = this.addItemForm.itemCatId
//静态属性
let type = 2
let {
data: result
} = await this.$http.get("/itemCatParam/findItemCatParamListByType", {
params: {
paramType: type,
itemCatId: itemCatId
}
})
if (result.status !== 200) return this.$message.error("商品分类参数查询失败")
this.staticTableData = result.data
}
},
//预览图片的方法
handlePreview(file) {
//获取图片的虚拟路径
this.imageUrlPath = file.response.data.urlPath
this.dialogImageVisible = true
},
//移除图片的方法
async handleRemove(file) {
//移除数组中的数据
let virtualPath = file.response.data.virtualPath
//通过findIndex函数 获取数组中指定数据的位置
let index = this.addItemForm.images.findIndex(x => x === virtualPath)
//删除数组中指定的数据
this.addItemForm.images.splice(index, 1)
//删除服务中的文件
let {
data: result
} = await this.$http.delete("/file/deleteFile", {
params: {
virtualPath: virtualPath
}
})
if (result.status !== 200) return this.$message.error("删除图片失败")
this.$message.success("删除图片成功")
},
//如果文件上传成功之后调用
handleSuccess(response, file) {
if (response.status !== 200) return this.$message.error("文件上传失败")
file.name = response.data.fileName
//获取虚拟路径
let virtualPath = response.data.virtualPath
//将数据封装到Form表单中
this.addItemForm.images.push(virtualPath)
},
/* 添加商品按钮 */
async addItemBtn(){
//console.log(this.addItemForm)
//1.完成表单校验
this.$refs.addItemFormRef.validate( valid => {
if(!valid) return this.$message.error("请输入商品必填项")
})
//2.完成商品参数的封装
//2.0 将商品价格扩大100倍
this.addItemForm.price = this.addItemForm.price * 100
//2.1 将商品图片的数据转化为字符串
this.addItemForm.images = this.addItemForm.images.join(",")
//2.2 将商品参数封转为对象 {paramId: vals}
this.dynamicTableData.forEach(item => {
let dynamicArg = {paramId : item.paramId, paramVals: item.paramVals.join(",")}
this.itemParam.dynamicArray.push(dynamicArg)
})
//2.3 将商品静态属性封装为对象
this.staticTableData.forEach(item => {
let staticArg = {paramId:item.paramId,paramVals:item.paramVals}
this.itemParam.staticArray.push(staticArg)
})
//2.5 实现商品数据提交
let submitAddItem = {
item : this.addItemForm,
itemDesc: this.itemDesc,
itemParam: this.itemParam
}
console.log(submitAddItem)
let {data: result} = await this.$http.post("/item/saveItem",submitAddItem)
if(result.status !== 200) return this.$message.error("商品添加失败")
this.$message.success("商品添加成功")
//2.5添加完成之后,将数据重定向到商品展现页面
this.$router.push("/item")
}
}
}
</script>
<style lang="less" scoped>
.el-steps {
margin: 20px 0;
}
.el-cascader {
width: 30%;
}
/* 控制复选框的右边距5像素 !important 表示优先执行 IE6不兼容*/
.el-checkbox {
margin: 0 10px 0 0 !important;
}
.addItemBtnClass{
margin-top: 15px;
}
</style>
跳转页面效果
文件上传
官网API介绍
当管理员上传图片的之后,比如一个软件,当管理员上传图片的之后,当我们去下载该软件的时候也会将该图片进行下载,并且还会自动的生成该图片路径,由于将来会部署到liux系统,在liux的系统中没相应的磁盘路径,所以不能保存磁盘路径;
编辑文件上传页面
<!--
class="upload-demo" 图片上传的类型
:action="uploadUrl" 必选参数,上传的地址
:on-preview="handlePreview" 当上传图片之后预览的回调
:on-remove 删除图片的回调函数
:on-success 上传成功的回调
list-type="picture" 上传文件的类型 只允许上传图片
multiple 是否支持多选文件
drag 是否允许拖拽
请求的参数名称: file
-->
<el-upload class="upload-demo" :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove"
:on-success="handleSuccess" list-type="picture" multiple drag>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
文件上传接口文档
编辑FileController
原理:当管理员上传图片的之后,比如一个软件,当管理员上传图片的之后,当我们去下载该软件的时候也会将该图片进行下载,并且还会自动的生成该图片路径;
package com.jt.controller;
import com.jt.service.FileService;
import com.jt.vo.ImageVO;
import com.jt.vo.ItemVO;
import com.jt.vo.SysResult;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {
/**
* Demo
* URL:http://localhost:8091/file/upload
* 参数: file:二进制信息
* 返回值: SysResult对象
* MultipartFile:SpringMVC 对外提供的接口 专门实现文件上传操作
* 高级API 默认的文件大小 最大1M
* 如果需要优化则需要编辑配置类 重新定义大小(一般不这么做)
* 优化: 1.防止文件重名
* 2.防止恶意程序 jpg|png|gif
*/
@PostMapping("/upload")
public SysResult upload(MultipartFile file) throws IOException {
//1.获取文件名称
String fileName = file.getOriginalFilename();
//2.准备文件上传的本地目录
String fileDir = "D:/JT_IMAGE/";
//3.是否需要判断目录是否存在
File filePath = new File(fileDir);
if(!filePath.exists()){
//可以创建多级目录
filePath.mkdirs();
/*只创建一级目录
filePath.mkdir();**/
}
//4.准备输出的对象 文件的全路径="文件目录"/+"文件的名称"
String realFilePath = fileDir + fileName;
File realFile = new File(realFilePath);
//5.实现文件上传
file.transferTo(realFile);
return SysResult.success();
}
}