在这里插入图片描述
一 根据id删除一个
前端请求
export const BrandDel =(params) =>{return axios.delete("/api/erpBrand/del?id=" + params).then(res => res.data) };
后端接受
@DeleteMapping("/del")
public R deleteById(Long id) {
logger.info("前端传入id{}"+id);
return R.ok(this.erpBrandService.deleteById(id));
}
二echart报表前端
1设置容器
<template>
<div>
<!-- 1设置容器 -->
<div id="chart" style="width: 600px; height: 400px;"></div>
</div>
</template>
2钩子函数
mounted() {
this.initChart()
},
3方法内使用
methods: {
initChart() {
// 2初始化
const chart = echarts.init(document.getElementById('chart'))
// 3配置
axios.get('/api/erpGoods/echarts').then(res => {
console.log("res",res)
let retData = res.data.data;
// const options = {
// title: {
// text: '商品分类数量展示'
// },
// tooltip: {
// trigger: 'axis'
// },
// legend: {
// data: ['商品分类']
// },
// xAxis: {
// type: 'category',
// data: retData.Type // 从后端获得x轴展示内容
// },
// yAxis: {
// type: 'value'
// },
// series: [
// {
// name: '商品分类',
// type: 'bar',
// data: retData.Num // 从后端获得x轴展示数据
// }
// ]
// }
// 使用图表配置
// chart.setOption(options)
var data = [];
for (var i = 0; i < retData.Num.length; i++) {
data.push({ value: retData.Num[i], name: retData.Type[i] });
}
const option = {
title: {
text: '商品分类数量统计',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left',
itemHeight: 10,
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
center:['60%','50%'],
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
option && chart.setOption(option);
})
}
}
前端展示
柱状图’bar’
饼状图’pie’
后端代码
/**
* 查全部数据里的分类和分类数量
* */
@GetMapping("/echarts")
public R showEcharts() {
List<HashMap<String,Object>> resultMap = erpGoodsService.queryTypeNum();
ArrayList<String> typeList = new ArrayList<>( );
ArrayList<Object> numList = new ArrayList<>( );
resultMap.forEach(map -> {
String type = (String)map.get("type");
typeList.add(type);
Object num=map.get("num");
numList.add(num);
});
HashMap<String, Object> map = new HashMap<>( );
map.put("Type",typeList);
map.put("Num",numList);
/**
* {
* Type: [类型],
* Num: [num]
* }
*/
return R.ok(map);
}
mapper.xml
<select id="queryTypeNum" resultType="java.util.HashMap">
SELECT type,count(goods_id) num
from erp_goods
GROUP BY type
</select>
mapper
List<HashMap<String,Object>> queryTypeNum();
三导入导出Excel
pom
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
前端按钮
<el-button size="small" type="primary" icon="el-icon-plus" @click="importExcel()">导入商品</el-button>
<el-button size="small" type="success" icon="el-icon-upload2" @click="exportExcel()">导出商品</el-button>
绑定事件
data(){
return{
dialogUpVisible:false,
}
},
importSuccess(){
this.dialogUpVisible=false
this.$message.success("导入成功!")
},
importExcel(){
this.dialogUpVisible=true
},
前端导入操作类
<el-dialog title="导入" :visible.sync="dialogUpVisible" width="30%">
<el-upload
class="upload-demo"
drag
action="http://localhost:9999/api/erpGoods/import"
name="file"
method="post"
accept=".xlsx,.xls"
:on-success="importSuccess"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传xlsx/xls文件b</div>
</el-upload>
</el-dialog>
后端接口
/**
* 导入excel实体数据
* */
@PostMapping("/import")
public R importExcel(MultipartFile file) throws IOException {
// 别忘了给SysUserReadListener构造方法传入SysUserService对象
EasyExcel.read(file.getInputStream(),
ErpGoods.class,
new ErpGoodsReadListener(erpGoodsService)).sheet().doRead();
return R.ok();
}
实体类格式
@Data
@NoArgsConstructor
@AllArgsConstructor
@HeadRowHeight(20) // 指定列头行高
@ColumnWidth(20)
public class ErpGoods implements Serializable {
private static final long serialVersionUID = 163297199659489178L;
/**
* 商品ID
*/
@ExcelIgnore
private Long goodsId;
/**
* 图片
*/
@ExcelIgnore
private String goodsImg;
/**
* 品名/SKU
*/
@ExcelProperty(value="品名/SKU",index=0)
private String productName;
/**
* 分类
*/
@ExcelProperty(value="分类",index=1)
private String type;
/**
* 品牌
*/
@ExcelProperty(value="品牌",index=2)
private String brand;
/**
* 采购人
*/
@ExcelProperty(value="采购人",index=3)
private String buyName;
/**
* 采购成本
*/
@ExcelIgnore
private Double purchasingCost;
/**
* 创建日期
*/
@ExcelProperty(value="创建日期",index=4)
private Date createDate;
/**
* 状态
*/
@ExcelIgnore
private String status;
导入工具类
package com.raccoon.erpsys.utils;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.raccoon.erpsys.entity.ErpGoods;
import com.raccoon.erpsys.service.ErpGoodsService;
import java.util.ArrayList;
public class ErpGoodsReadListener extends AnalysisEventListener<ErpGoods> {
// 有个很重要的点 DemoDataListener 不能被spring管理,
// 要每次读取excel都要new,然后里面用到spring可以构造方法传进去
private ErpGoodsService erpGoodsService;
public ErpGoodsReadListener(){} // 空参构造
// 有参构造
public ErpGoodsReadListener(ErpGoodsService erpGoodsService){
this.erpGoodsService = erpGoodsService;
}
// 每隔5条存储数据库,实际项目中使用时可以100条,然后清理list ,方便内存回收
private final int BATCH_COUNT = 5;
private ArrayList<ErpGoods> list = new ArrayList<>( );
// 每读一样,会调用该invoke方法一次
@Override
public void invoke(ErpGoods data, AnalysisContext context) {
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size( ) >= BATCH_COUNT) {
saveData( );
// 存储完成清理 list
list.clear();
}
}
// 全部读完之后,会调用该方法
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
if(list.size()!=0){
saveData( );
}
System.out.println("所有数据解析完成!");
}
private void saveData() {
System.out.println("开始存储数据库!");
// 调用业务层存数据库
erpGoodsService.saveBatch(list);
System.out.println("存储数据库成功!");
}
}
service
int saveBatch(ArrayList<ErpGoods> list);
serviceImpl
@Override
public int saveBatch(ArrayList<ErpGoods> list) {
return erpGoodsMapper.saveBatch(list);
}
mapper
int saveBatch(ArrayList<ErpGoods> list);
mapper.xml
<insert id="saveBatch" >
insert into erp_goods(goods_img, product_name, type, brand, buy_name, purchasing_cost, create_date, status)
values
<foreach collection="list" item="entity" separator=",">
(#{entity.goodsImg}, #{entity.productName}, #{entity.type}, #{entity.brand}, #{entity.buyName}, #{entity.purchasingCost}, #{entity.createDate}, #{entity.status})
</foreach>
</insert>
导出前端
exportExcel(){
this.$confirm('确定要导出数据吗?, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.request({
url:'/api/erpGoods/export',
method:'get',
responseType:'blob',
}).then(res=>{
this.download(res,"系统用户信息")
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消导出'
});
});
},
download(res,name){
console.log("调用download之后",res,name)
if(!res){
return;
}
console.log("res",res)
let url =window.URL.createObjectURL(new Blob([res.data],
{type:"application/vnd.ms-excel"}))
let link=document.createElement('a');
link.style.display='none';
link.href=url;
link.setAttribute('download',name);
document.body.appendChild(link);
link.click();
},
后端接口
/**
* 导出excel实体数据
* */
@GetMapping("/export")
public void exportExcel(HttpServletResponse response) throws IOException {
// 调用业务层,查询全部数据
List<ErpGoods> list = erpGoodsService.queryAll();
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream(), ErpGoods.class).autoCloseStream(Boolean.FALSE).sheet("商品信息")
.doWrite(list);
}
四批量删除前端传递数组
前端请求
export const GoodsDelAll= (params) =>{return axios.post("/api/erpGoods/delAll",params)}
后端接收
/**
* 批量删除数据
*
* @param ids
* @return 删除是否成功
*/
@PostMapping("/delAll")
public R delAll(@RequestBody List<Integer> ids){
int i = erpGoodsService.delAll(ids);
return R.ok(i);
}
mapper.xml
<delete id="delAll">
delete from erp_goods where goods_id in
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
五post请求以表单形式发送
前端
export const GoodsEdit = (params) => { return req("post", "/api/erpGoods/edit", params) };
前端封装请求格式
const req = (method, url, params) => {
return axios({
method: method,
url: url,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
token: localStorage.getItem('logintoken')
},
data: params,
traditional: true,
transformRequest: [
function(data) {
let ret = ''
for (let it in data) {
ret +=
encodeURIComponent(it) +
'=' +
encodeURIComponent(data[it]) +
'&'
}
return ret
}
]
}).then(res => res.data);
};
后端接受
/**
* 编辑数据
*
* @param erpGoods 实体
* @return 编辑结果
*/
@PostMapping("/edit")
public R edit(ErpGoods erpGoods) {
return R.ok(this.erpGoodsService.update(erpGoods));
}
六联查
有分类表有品牌表 当添加商品时商品下拉选择有的品牌和分类
在添加组件中用生命周期函数查询所有分类和所有品牌显示在添加下拉框内
前端代码
<el-form-item label="分类" prop="type">
<!--<el-input v-model.number="ruleForm.type"></el-input>-->
<template>
<el-select v-model="ruleForm.type" placeholder="请选择">
<el-option
v-for="item in typeName"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</template>
</el-form-item>
后端接口
/**
* 查询全部的分类名
* */
@PostMapping("/queryTN")
public R queryTN(){
List<String> typeName = erpGoodstypeService.queryTN();
return R.ok(typeName);
}
/**
* 查询全部品牌
* @param
* @return list
* */
@PostMapping("/queryBN")
public R queryBN(){
List<String> brandName = erpBrandService.queryBN();
return R.ok(brandName);
}
mapper.xml
<!--查询所有品牌名-->
<select id="queryBN" resultType="java.lang.String">
select brand_name from erp_brand
</select>
七上传头像
pom.xml
<!-- 使用工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
后端
/**
* upload file
*/
@PostMapping("/upload")
public R upload(MultipartFile img, HttpServletRequest request) throws IOException {
// 1.获得上传的对象 参数img就是文件对象
// 2. 获得最终上传的目的地路径(上传至服务器中当前项目下)
// 通过servlet方法获得路径,即最终上传到Tomcat的/upload
String realPath = request.getServletContext().getRealPath("/upload");
System.out.println(realPath);
// 2.1 将最终目的文件夹创建出来
File file = new File(realPath);
// 判断该文件是否存在
if(!file.exists()) {
// 不存在则创建出
file.mkdir();
}
// 2.2 获得文件名
/*
* 文件名重复时不能重复上传文件
*/
String fileName = img.getOriginalFilename();
System.out.println(fileName);
/*
* 根据.拆分字符串,获得文件后缀名
*/
String[] split = fileName.split("\\.");
System.out.println(Arrays.toString(split));
String suffix = split[split.length-1];
// 以当前毫秒值为文件名
long prefix = System.currentTimeMillis();
// 组装文件名
String newFileName = prefix+"."+suffix;
System.out.println("新的文件名 : "+newFileName);
// 2.3 确定上传路径
File newFile = new File(file,newFileName);
// 3. 用工具上传
FileUtils.writeByteArrayToFile(newFile, img.getBytes());
// 4 返回路径,测试使用,放查看是否上传成功
// String path = "http://localhost:8081/upload/"+newFileName;
System.out.println("http://localhost:8848/upload/"+newFileName );
HttpSession session = request.getSession( );
SysUser sysUser = (SysUser) session.getAttribute("user");
SysUser user = new SysUser( );
user.setUserId(sysUser.getUserId());
user.setAvatar("http://localhost:8848/upload/"+newFileName);
int i = sysUserService.update(user);
return R.ok("http://localhost:8848/upload/"+newFileName);
}
前端
<el-dialog title="修改头像" :visible.sync="dialogVisible" width="20%" @close="dialogVisible = false">
<el-upload
class="avatar-uploader"
action="http://localhost:9999/api/sysUser/upload"
:show-file-list="true"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
name="img">
<img v-if="imageUrl" :src="imageUrl" class="avatar-2">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-dialog>
事件
handleAvatarSuccess(res, file) {
console.log("res",res,"文件",file)
if(res.code===200){
this.dialogVisible=false
this.circleUrl=res.data+""
console.log("对circleUrl赋值后",this.circleUrl)
}
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
八日志log4j
pom.xml
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- 去掉springboot默认配置 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
在resourcse建一个log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- status log4j2内部输出自身的日志信息的级别,可以不设置,没太大用 -->
<!-- configuration中主要包括有 Properties、Appenders、Loggers标签 -->
<Configuration status="fatal" monitorInterval="30">
<!--打印在本地,根据具体存储地址填写 ./logs是当前项目名下的位置-->
<Properties>
<Property name="baseDir" value="./logs"/>
<!--
常见的配置如下:
- %d{yyyy-MM-dd HH:mm:ss.SSS} : 日志生成时间,输出格式为“年-月-日 时:分:秒.毫秒”
- %p : 日志输出格式
- %c : logger的名称
- %m : 日志内容,即 logger.info("message")
- %n : 换行符
- %T : 线程号
- %L : 日志输出所在行数
- %M : 日志输出所在方法名
-->
<Property name="pattern">%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{1}:%L -%m%n</Property>
</Properties>
<!-- 输出源,常见的主要有Console、RollingFile、File 三种子节点
Console:用于定义输出到控制台的Appender
RollingFile:定义指定方式触发新的Appender
-->
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
</Console>
<!--debug级别日志文件输出-->
<!--<RollingFile name="debug_appender" fileName="${baseDir}/debug.log"-->
<!-- filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}">-->
<!-- <!– 过滤器 –>-->
<!-- <Filters>-->
<!-- <!– 限制日志级别在debug及以上在info以下 –>-->
<!-- <ThresholdFilter level="debug"/>-->
<!-- <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>-->
<!-- </Filters>-->
<!-- <!– 日志格式 –>-->
<!-- <PatternLayout>-->
<!-- <pattern>${pattern}</pattern>-->
<!-- </PatternLayout>-->
<!-- <!– 策略 –>-->
<!-- <Policies>-->
<!-- <!– 每隔一天转存 –>-->
<!-- <TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
<!-- <!– 文件大小 –>-->
<!-- <SizeBasedTriggeringPolicy size="100 MB"/>-->
<!-- </Policies>-->
<!--</RollingFile>-->
<!-- info级别日志文件输出 -->
<!--<RollingFile name="info_appender" fileName="${baseDir}/info.log"-->
<!-- filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}">-->
<!-- <!– 过滤器 –>-->
<!-- <Filters>-->
<!-- <!– 限制日志级别在info及以上在error以下 –>-->
<!-- <ThresholdFilter level="info"/>-->
<!-- <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>-->
<!-- </Filters>-->
<!-- <!– 日志格式 –>-->
<!-- <PatternLayout>-->
<!-- <pattern>${pattern}</pattern>-->
<!-- </PatternLayout>-->
<!-- <!– 策略 –>-->
<!-- <Policies>-->
<!-- <!– 每隔一天转存 –>-->
<!-- <TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
<!-- <!– 文件大小 –>-->
<!-- <SizeBasedTriggeringPolicy size="100 MB"/>-->
<!-- </Policies>-->
<!--</RollingFile>-->
<!-- error级别日志文件输出 -->
<RollingFile name="error_appender" fileName="${baseDir}/error.log"
filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}">
<!-- 过滤器 -->
<Filters>
<!-- 限制日志级别在error及以上 -->
<ThresholdFilter level="error"/>
</Filters>
<!-- 日志格式 -->
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
<Policies>
<!-- 每隔一天转存 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- 文件大小 -->
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<!-- 这是总的级别配置,优先级比Appenders中的要高 -->
<Root level="DEBUG">
<AppenderRef ref="Console"/>
<AppenderRef ref="debug_appender"/>
<AppenderRef ref="info_appender"/>
<AppenderRef ref="error_appender"/>
</Root>
</Loggers>
</Configuration>
使用
private Logger logger = LogManager.getLogger(SysUserController.class);
九AOP实战-log记录
pom.xml
<!--Aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
日期sql
CREATE TABLE `log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`log_time` datetime DEFAULT NULL,
`log` varchar(255) DEFAULT NULL,
`ip` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
日志注解文件
package com.qf.annotation;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String value();
}
使用注解
@RestController
public class UserController {
@Autowired
private UserService userService;
/**
* 先登录,登录成功后将信息存入Session
* 这样log日志记录时才能取出人名
*/
@GetMapping("/login")
public User login(String name, HttpSession session) {
User user = userService.selectUserByUsername(name);
if (user != null) {
session.setAttribute("user",user);
}
return user;
}
@GetMapping("/list")
@MyLog("查询全部") // 使用日志注解
public List<User> selectAll() {
return userService.selectAll();
}
}
切面类
package com.qf.aspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import com.qf.annotation.MyLog;
import com.qf.model.Log;
import com.qf.model.User;
import com.qf.service.MyLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.WebUtils;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
@Component
@Aspect
public class MyLogAspect {
// 注入业务层对象
@Autowired
private MyLogService logService;
// 切入的目标是注解
@Before("@annotation(com.qf.annotation.MyLog)")
public void after(JoinPoint joinPoint) {
// 调用下方自定义方法,获得注解中的值
String desc = getAnnoDesc(joinPoint);
System.out.println("注解中的值:" + desc);
// 以下代码需要使用Springmvc,既控制层也需要由Spring托管,才会获得ip
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes( )).getRequest( );
// 能取出数据的前提是登录时将用户信息存储到session
User user = (User) WebUtils.getSessionAttribute(request, "user");
String name = "未登录";
if (user != null) { // 防止出现空指针异常
name = user.getName( );
}
//ip
String ip = request.getRemoteAddr( );
System.out.println("请求对象的ip:" + ip);
// 封装数据
Log log = new Log( );
log.setName(name);
log.setIp(ip);
log.setLogTime(new Date());
log.setLog(desc);
// 调用业务层,执行插入
logService.insertLog(log);
}
/*
* 封装的方法,通过反射技术获得目标方法上的注解的值
*/
public static String getAnnoDesc(JoinPoint joinPoint){
String value = "";
// 获得目标方法名
String methodName = joinPoint.getSignature( ).getName( );
System.out.println("---------->" + methodName );// 目标方法名
// 根据目标方法所在的对象得到该类的全部方法
Method[] methods = joinPoint.getTarget().getClass().getDeclaredMethods();
/*
* 1.遍历所有方法
* 2.找到与目标方法一样的方法
* 3.找到该方法上的所有注解
* 4.遍历所有注解,判断注解的类型是否是我们自定义的日志注解
* 5.如果是,就获取该注解对象
* 6.由注解对象得到注解值
*/
// 1.遍历所有方法
for (Method method : methods) {
// 2.找到与目标方法一样的方法
if (methodName.equals(method.getName())) {
// 3.找到该方法上的所有注解
Annotation[] annotations = method.getDeclaredAnnotations();
// 4.遍历所有注解,判断注解的类型是否是我们自定义的日志注解
for (Annotation annotation : annotations) {
// 5.如果是,就获取该注解对象
if (annotation.annotationType( ).equals(com.qf.util.Log.class)) {
// 6.由注解对象得到注解值
value = method.getAnnotation(com.qf.util.Log.class).value( );
return value;
}
}
}
}
return value;
}
}
十两表联查
前端
<el-form-item label="品牌" prop="brand">
<!--<el-input v-model.number="ruleForm.brand"></el-input>-->
<template>
<el-select v-model="ruleForm.brand" placeholder="请选择">
<el-option
v-for="item in BrandName"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</template>
</el-form-item>
事件和绑定变量
data(){
return{
BrandName:[],
}
}
method:{
getTypeName(){
TypeQueryTN().then(res=>{
if(res.code===2000){
console.log("BrandQueryBN",res)
this.typeName=res.data
}
})
},
}
后端
/**
* 查询全部品牌
* @param
* @return list
* */
@PostMapping("/queryBN")
public R queryBN(){
List<String> brandName = erpBrandService.queryBN();
return R.ok(brandName);
}
mapper.xml
<!--查询所有品牌名-->
<select id="queryBN" resultType="java.lang.String">
select brand_name from erp_brand
</select>
十一ElemenntUI组件
面包屑
<!-- 面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>品牌管理</el-breadcrumb-item>
</el-breadcrumb>
下拉选择框
<template>
<el-select v-model="ruleForm.brand" placeholder="请选择">
<el-option
v-for="item in BrandName"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</template>
头部菜单
<el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" text-color="#fff" active-text-color="#fff">
<el-button class="buttonimg">
<img class="showimg" :src="collapsed?imgsq:imgshow" @click="toggle(collapsed)">
</el-button>
<el-submenu index="2" class="submenu">
<template slot="title">{{erpuser.userName}}</template>
<!--<template slot="title">超级管理员</template>-->
<!--<el-menu-item @click="content1()" index="2-1">修改密码</el-menu-item>-->
<el-menu-item @click="content()" index="2-2">个人中心</el-menu-item>
<el-menu-item @click="exit()" index="2-3">退出</el-menu-item>
</el-submenu>
</el-menu>
十二添加用户异步校验是否存在
前端
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{validator: validateUserName, trigger: 'blur'}
],
var validateUserName = (rule, value, callback) => {
console.log(value)
axios.post('api/sysUser/count',{
userName:value
}).then(res=>{
console.log("返回数据",res.data)
if(res.data.data>0){
callback(new Error('用户名已存在'))
}else{
callback()
}
})
}
``