赞
踩
1).编辑路由文件
2).指定路由占位符
3).路由测试
当用户访问 根目录时,要求重定向到登陆组件
将课前资料中的文件导入项目中
1).定义表单校验规则
2).定义校验规则JS
3).效果展现
当点击重置表单按钮时 应该清空数据
当用户输入数据之后,需要对数据进行校验.当数据有效时 才能提交数据.
说明:在main.js中添加如下代码
/* 导入axios包 */
import axios from 'axios'
/* 设定axios的请求根目录 */
axios.defaults.baseURL = 'http://localhost:8091/'
/* 向vue对象中添加全局对象 以后发送ajax请求使用$http对象 */
Vue.prototype.$http = axios
{"status":200,"msg":"服务器调用成功!","data":"1e893a97634847b3a8b499b173bea620"}
说明: 当用户登陆成功之后,将token保存到客户端中的sessionStorage中. 因为用户的其他操作都必须保证用户已经登录之后才能操作. 所以通过SessionStorage保存用户的token记录 表示已经登陆.
当用户没有登录时,不可以访问其他页面 如果sessionStorage中没有token数据,则表示没有登录 用该拦截,跳转到登录页面.
编辑router的index.js
//设置路由导航守卫
//关于参数说明:
//1. to 将要访问的路径
//2. from 从哪个路径跳转来的
//3. next 是一个函数 next() 表示放行 next("/login") 强制跳转
router.beforeEach((to,from,next) => {
//1.当用户访问登录页面,则直接放行 如果不需要执行后续操作 执行return
if(to.path === '/login') return next()
//2.当用户访问其他页面 需要校验是否有token
let token = window.sessionStorage.getItem('token')
//如果数据为null 则访问登录页面
if(!token) return next('/login')
//如果数据不为null 则放行
next()
})
当用户点击退出按钮时,应该删除sessionStorage中的token信息. 并且访问登录页面
页面效果:
package com.jt.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.jt.mapper.RightsMapper; import com.jt.pojo.Rights; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.stereotype.Service; import java.util.List; /** * @author 刘昱江 * 时间 2021/5/12 */ @Service public class RightsServiceImpl implements RightsService{ @Autowired private RightsMapper rightsMapper; @Override public List<Rights> getRightsList() { //1.查询所有的一级菜单 QueryWrapper<Rights> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("parent_id", 0); List<Rights> oneList = rightsMapper.selectList(queryWrapper); //2.根据一级查询二级菜单 for (Rights oneRights : oneList){ //查询二级菜单 QueryWrapper<Rights> queryWrapper2 = new QueryWrapper<>(); queryWrapper2.eq("parent_id", oneRights.getId()); List<Rights> twoList = rightsMapper.selectList(queryWrapper2); oneRights.setChildren(twoList); } return oneList; } }
属性介绍:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
定义子组件请求路径
说明: 添加welcome页面
定义路由组件: 实现默认跳转
<!-- 1.定义面包屑导航 -->
<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>
<!-- 2.定义卡片视图 -->
<el-card class="box-card">
<h1>我是一个卡片视图</h1>
</el-card>
使用栅格是为了固定内容的大小 el-row 表示一行 :span=24 一行最多24个 代表宽度
<!-- 2.定义卡片视图 --> <el-card class="box-card"> <!-- 3.定义栅格的一行 :gutter="20"定义行间距 :span="9" 占位符 --> <el-row :gutter="20"> <el-col :span="9"> <!-- 3.定义搜索框 --> <el-input placeholder="请输入内容"> <el-button slot="append" icon="el-icon-search"></el-button> </el-input> </el-col> <el-col :span="4"> <!-- 定义添加按钮--> <el-button type="primary">添加用户</el-button> </el-col> </el-row> </el-card>
官网API:
package com.jt.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author 刘昱江 * 时间 2021/5/13 */ @Configuration public class MybatisPlusConfig { // 最新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MARIADB)); return interceptor; } }
<script> export default { data(){ return { queryInfo: { query: '', pageNum: 1, pageSize: 5 }, //为了后续操作 定义数据在外边 userList: [], total: 0 } }, methods: { async getUserList(){ const {data: result} = await this.$http.get('/user/list',{ params: this.queryInfo }) if(result.status !== 200) return this.$message.error("用户列表查询失败") this.userList = result.data.rows this.total = result.data.total } }, //利用钩子函数实现数据查询 mounted(){ this.getUserList() } } </script>
作用域插槽: slot-scope=“scope”
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
编辑页面JS
效果展现
在switch中 通过change事件可以实现数据的修改
通过回调函数和作用域插槽 实现数据传递
当用户点击按钮之后,将数据绑定到查询对象中,重新获取列表数据即可.
说明: 当用户输入成功之后,可以通过清空属性 已写数据 实现查询全部的功能
清空事件: 当用户调用clearable之后,调用clear事件
触发页面JS
1).绘制Dialog对话框
<!-- 编辑用户新增对话框 visible.sync 控制对话框的显示--> <el-dialog title="添加用户" :visible.sync="dialogVisible" width="50%"> <!-- 定义用户提交表单数据--> <el-form :model="addUserModel" :rules="rules" ref="addUserRef" label-width="100px" class="demo-ruleForm"> <el-form-item label="用户名" prop="username"> <el-input v-model="addUserModel.username"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input v-model="addUserModel.password" type="password"></el-input> </el-form-item> <el-form-item label="密码确认" prop="password2"> <el-input v-model="addUserModel.password2" type="password"></el-input> </el-form-item> <el-form-item label="电话" prop="phone"> <el-input v-model="addUserModel.phone"></el-input> </el-form-item> <el-form-item label="邮箱" prop="email"> <el-input v-model="addUserModel.email"></el-input> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span> </el-dialog>
//校验邮箱规则 rule校验规则 value校验的数据 callback回调函数 const checkEmail = (rule, value, callback) => { //定义邮箱的正则表达式 JS中用/来表示正则表达式的开始和结束 const emailRege = /^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$/ //正则表达式语法校验 test(xx) 校验成功 返回true 校验失败返回false if (emailRege.test(value)) { //表示邮箱合法 正确返回 return callback() } callback(new Error('请填写正确的邮箱地址')) } //校验手机号的邮箱规则 const checkPhone = (rule, value, callback) => { //定义校验手机号的正则语法 const phoneRege = /^1[34578][0-9]{9}$/ if (phoneRege.test(value)) { return callback() } callback(new Error('请填写正确的手机号')) } const checkPassword = (rule, value, callback) => { if(this.addUserModel.password !== value) return callback(new Error('2次密码输入不一致')) //否则校验成功 callback() }
使用校验规则
页面效果:
<!-- 定义修改页面 --> <el-dialog title="修改用户" :visible.sync="updateDialogVisible" width="50%"> <!-- 定义用户提交表单数据--> <el-form :model="updateUserModel" :rules="rules" ref="updateUserRef" label-width="100px"> <el-form-item label="用户名" prop="username"> <el-input v-model="updateUserModel.username" disabled ></el-input> </el-form-item> <el-form-item label="电话" prop="phone"> <el-input v-model="updateUserModel.phone"></el-input> </el-form-item> <el-form-item label="邮箱" prop="email"> <el-input v-model="updateUserModel.email"></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="updateDialogVisible = false">确 定</el-button> </span> </el-dialog>
async updateUserBtn(user){
this.updateDialogVisible = true
const {data: result} = await this.$http.get("/user/"+user.id)
if(result.status !== 200) return this.$message.error("用户查询失败")
this.updateUserModel = result.data
}
@Override public List<ItemCat> findItemCatList(Integer type) { //获取数据 Map<Integer,List<ItemCat>> map = getItemCatMap(); return findChildrenList(null,type,map); } public List<ItemCat> findChildrenList(Integer id,Integer type, Map<Integer,List<ItemCat>> map){ if(id==null) id = 0; List<ItemCat> itemCatList = map.get(id); if(type == 1){ return itemCatList; } if(itemCatList == null){ return null; } for (ItemCat itemCat: itemCatList){ if(itemCat.getLevel()<type){ List<ItemCat> childrenList = findChildrenList(itemCat.getId(),type,map); itemCat.setChildren(childrenList); } } return itemCatList; } public Map<Integer,List<ItemCat>> getItemCatMap(){ List<ItemCat> itemCatList = itemCatMapper.selectList(null); Map<Integer,List<ItemCat>> map = new HashMap<>(); for(ItemCat itemCat : itemCatList){ Integer parentId = itemCat.getParentId(); if(map.containsKey(parentId)){ map.get(parentId).add(itemCat); }else{ List<ItemCat> list = new ArrayList<>(); list.add(itemCat); map.put(parentId, list); } } return map; } 方式2: @Override public List<ItemCat> findItemCatList(Integer type) { Map<Integer,List<ItemCat>> map = getItemCatMap(); if(type == 1) return map.get(0); if(type == 2) return findTwoItemCatList(map); return findThreeItemCatList(map); } public List<ItemCat> findTwoItemCatList(Map<Integer,List<ItemCat>> map){ //1.获取一级商品分类 List<ItemCat> oneList = map.get(0); //2.根据一级查询二级 for(ItemCat itemCat : oneList){ List<ItemCat> twoList = map.get(itemCat.getId()); itemCat.setChildren(twoList); } return oneList; } private List<ItemCat> findThreeItemCatList(Map<Integer,List<ItemCat>> map) { List<ItemCat> twoList = findTwoItemCatList(map); for (ItemCat itemCat : twoList){ //1级菜单 if(itemCat.getChildren() !=null){ for(ItemCat itemCat2 :itemCat.getChildren()){ List<ItemCat> threeList = map.get(itemCat2.getId()); itemCat2.setChildren(threeList); } } } return twoList; } public Map<Integer,List<ItemCat>> getItemCatMap(){ List<ItemCat> itemCatList = itemCatMapper.selectList(null); Map<Integer,List<ItemCat>> map = new HashMap<>(); for(ItemCat itemCat : itemCatList){ Integer parentId = itemCat.getParentId(); if(map.containsKey(parentId)){ map.get(parentId).add(itemCat); }else{ List<ItemCat> list = new ArrayList<>(); list.add(itemCat); map.put(parentId, list); } } return map; }
@Override public void deleteItemCat(ItemCat itemCat) { if(itemCat.getLevel() == 3){ itemCatMapper.deleteById(itemCat.getId()); return; } if(itemCat.getLevel() == 2){ itemCatMapper.delete(new QueryWrapper<>(itemCat).eq("parent_id", itemCat.getId())); itemCatMapper.deleteById(itemCat.getId()); } if(itemCat.getLevel() == 1){ QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("parent_id", itemCat.getId()); List<ItemCat> list2 = itemCatMapper.selectList(queryWrapper); for (ItemCat itemCat2 : list2){ QueryWrapper<ItemCat> queryWrapperTemp = new QueryWrapper<>(); queryWrapperTemp.eq("parent_id", itemCat2.getId()); itemCatMapper.delete(queryWrapperTemp); itemCatMapper.deleteById(itemCat2.getId()); } itemCatMapper.deleteById(itemCat.getId()); } }
1).商品分类参数新增页面
2).新增商品分类参数
1).编辑页面JS
2).删除JS
1).文件上传操作
#配置windows服务器路径
image.localPathDir=D:/JT_IMAGE
#配置Linux服务器路径
#image.localPathDir=/usr/local/src/images
image.localUrlPath=http://image.jt.com
@Service @PropertySource("classpath:/properties/image.properties") public class FileServiceImpl implements FileService{ //为属性动态赋值 注解@Value @Value("${image.localPathDir}") private String localPathDir; // = "D:/JT_IMAGE"; @Value("${image.localUrlPath}") private String localUrlPath; // = "http://image.jt.com"; //1.参数 ~~~已知条件 //2.干什么 ~~~ 实现文件上传 //3.返回值: void ImageVO 有效返回 /** * 文件上传案例实现 * 1.如何保证前端是上传的数据是有效的!! * 1.1 校验文件的名称检查是否为图片 * 1.2 校验是否为恶意程序. * @param file * @return */ @Override public ImageVO upload(MultipartFile file) throws IOException { //1.1校验是否为图片类型 abc.jpg ABC.JPG 文件大小写 String fileName = file.getOriginalFilename(); //将所有的文件名称转化为小写 fileName = fileName.toLowerCase(); if(!fileName.matches("^.+\\.(jpg|png|gif)$")){ return null; } //1.2 校验图片类型是否为木马 try { BufferedImage bufferedImage = ImageIO.read(file.getInputStream()); int width = bufferedImage.getWidth(); int height = bufferedImage.getHeight(); if(width == 0 || height == 0 ){ return null; } }catch (Exception e){ return null; } //2. 目录结构 //2.1 实现分目录存储... 可以以时间维度进行分隔 /yyyy/MM/dd/ String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date()); //2.2 进行目录的拼接 "D:/JT_IMAGE/2021/11/11"; String localDir = localPathDir + datePath; //2.3 需要创建目录 File dirFile = new File(localDir); if(!dirFile.exists()){ dirFile.mkdirs(); } //3.文件名称重复 采用UUID防止文件重名 uuid.jpg String uuid = UUID.randomUUID().toString() .replace("-", ""); //fileName = abc.jpg String fileType = fileName.substring(fileName.lastIndexOf(".")); String realFileName = uuid + fileType; //c:jt_image/2021/11/11/uuid.jpg String filePathAll = localDir + realFileName; //实现文件上传 File realFile = new File(filePathAll); file.transferTo(realFile); //封装ImageVO对象 //2021/11/11/uuid.jpg 图片路径 String virtualPath = datePath + realFileName; //封装虚拟URl地址 http://image.jt.com/2021/11/11/uuid.jpg String urlPath = localUrlPath + virtualPath; return new ImageVO(virtualPath,urlPath,realFileName); } }
/** * 实现三张表入库 商品表/商品详情表/商品参数表 * @param itemVO */ @Transactional @Override public void saveItem(ItemVO itemVO){ //1.入库商品表 Item item = itemVO.getItem(); item.setStatus(true); //默认启用状态 //要求入库之后返回主键 //MP如果设定了主键自增则会自动的实现数据回显 itemMapper.insert(item); //2.入库商品详情 ItemDesc itemDesc = itemVO.getItemDesc(); itemDesc.setId(item.getId()); itemDescMapper.insert(itemDesc); //3.入库商品参数 //1.一个商品应该有自己的单独的参数. 动态参数/静态属性 KYE-VLAUE [key:value,key2:value2] ItemParam itemParam = itemVO.getItemParam(); ItemParamVO[] dynamic = itemParam.getDynamicArray(); ItemParamVO[] staticParam = itemParam.getStaticArray(); try { //将页面传递的数据转化为JSON,之后数据库保存 String dynamicJSON = MAPPER.writeValueAsString(dynamic); String staticJSON = MAPPER.writeValueAsString(staticParam); //封装商品参数信息 itemParam.setDynamicArgs(dynamicJSON) .setStaticArgs(staticJSON) .setId(item.getId()); //实现入库操作 itemParamMapper.insert(itemParam); } catch (JsonProcessingException e) { e.printStackTrace(); //如果程序执行报错 则抛出异常 throw new RuntimeException(e); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。