<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java1234.mapper.ProductMapper">
<resultMap id="productResult" type="com.java1234.entity.Product">
<association property="type" column="typeId" select="com.java1234.mapper.SmallTypeMapper.findById"></association>
</resultMap>
<select id="list" parameterType="Map" resultMap="productResult">
select * from t_product
<where>
<if test="name!=null and name!='' ">
and name like concat('%',#{name},'%')
</if>
</where>
<if test="start!=null and pageSize!=null ">
limit #{start},#{pageSize}
</if>
</select>
<select id="getTotal" parameterType="Map" resultType="Long">
select count(*) from t_product
<where>
<if test="name!=null and name!='' ">
and name like concat('%',#{name},'%')
</if>
</where>
</select>
<insert id="add" parameterType="com.java1234.entity.Product">
insert into t_product values(null,#{name},#{price},#{stock},#{proPic},#{hot},#{swiper},#{swiperPic},#{swiperSort},#{type.id},null,#{productIntroImgs},#{productParaImgs},#{description});
</insert>
<update id="update" parameterType="com.java1234.entity.Product">
update t_product
<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="price!=null">
price=#{price},
</if>
<if test="stock!=null">
stock=#{stock},
</if>
<if test="type!=null and type.id!=null">
typeId=#{type.id},
</if>
<if test="proPic!=null and proPic!=''">
proPic=#{proPic},
</if>
<if test="description!=null and description!=''">
description=#{description},
</if>
<if test="productIntroImgs!=null and productIntroImgs!=''">
productIntroImgs=#{productIntroImgs},
</if>
<if test="productParaImgs!=null and productParaImgs!=''">
productParaImgs=#{productParaImgs},
</if>
<if test="swiperPic!=null and swiperPic!=''">
swiperPic=#{swiperPic},
</if>
<if test="swiperSort!=null">
swiperSort=#{swiperSort},
</if>
</set>
where id=#{id}
</update>
<select id="findById" parameterType="Integer" resultMap="productResult">
select * from t_product where id=#{id}
</select>
</mapper>
package com.java1234.controller.admin;
import com.java1234.entity.*;
import com.java1234.service.IProductService;
import com.java1234.util.DateUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 管理端-商品Controller控制器
* @author java1234_小锋
* @site www.java1234.com
* @company 南通小锋网络科技有限公司
* @create 2022-02-14 6:54
*/
@RestController
@RequestMapping("/admin/product")
public class AdminProductController {
@Autowired
private IProductService productService;
@Value("${productImagesFilePath}")
private String productImagesFilePath;
/**
* 根据条件分页查询
* @param pageBean
* @return
*/
@RequestMapping("/list")
public R list(@RequestBody PageBean pageBean){
System.out.println(pageBean);
Map<String,Object> map=new HashMap<>();
map.put("name",pageBean.getQuery().trim());
map.put("start",pageBean.getStart());
map.put("pageSize",pageBean.getPageSize());
List<Product> productList = productService.list(map);
Long total = productService.getTotal(map);
Map<String,Object> resultMap=new HashMap<>();
resultMap.put("productList",productList);
resultMap.put("total",total);
return R.ok(resultMap);
}
/**
* 更新热门状态
* @param id
* @param hot
* @return
*/
@GetMapping("/updateHot/{id}/state/{hot}")
public R updateHot(@PathVariable(value = "id")Integer id,@PathVariable(value = "hot")boolean hot){
Product product=productService.getById(id);
product.setHot(hot);
if(hot){
product.setHotDateTime(new Date());
}else{
product.setHotDateTime(null);
}
productService.saveOrUpdate(product);
return R.ok();
}
/**
* 更新swiper状态
* @param id
* @param swiper
* @return
*/
@GetMapping("/updateSwiper/{id}/state/{swiper}")
public R updateSwiper(@PathVariable(value = "id")Integer id,@PathVariable(value = "swiper")boolean swiper){
Product product=productService.getById(id);
product.setSwiper(swiper);
productService.saveOrUpdate(product);
return R.ok();
}
/**
* 删除
* @param id
* @return
*/
@GetMapping("/delete/{id}")
public R delete(@PathVariable(value = "id")Integer id){
productService.removeById(id);
return R.ok();
}
/**
* 添加或修改
* @param product
* @return
*/
@RequestMapping("/save")
public R save(@RequestBody Product product){
System.out.println("product"+product);
if(product.getId()==null || product.getId() == -1){
productService.add(product);
}else{
productService.update(product);
}
return R.ok();
}
/**
* 上传商品大类图片
* @param file
* @return
* @throws Exception
*/
@RequestMapping("/uploadImage")
public Map<String,Object> uploadImage(MultipartFile file)throws Exception{
Map<String,Object> resultMap=new HashMap<>();
if(!file.isEmpty()){
//获取文件名
String originalFilename = file.getOriginalFilename();
String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName= DateUtil.getCurrentDateStr() + suffixName;
FileUtils.copyInputStreamToFile(file.getInputStream(),new File(productImagesFilePath+newFileName));
resultMap.put("code",0);
resultMap.put("msg","上传成功");
Map<String,Object> dataMap=new HashMap<>();
dataMap.put("title",newFileName);
dataMap.put("src","/image/product/"+newFileName);
resultMap.put("data",dataMap);
}
return resultMap;
}
}
@Value("${productImagesFilePath}")
private String productImagesFilePath;
1、用法示例: 在springMVC.xml配置文件中添加标签
(推荐用这个,这个用的比较多,也比较简洁)
<context:property-placeholder location=“classpath:salesman.properties”/>
加载多个
<context:property-placeholder location=“classpath:*.properties”/>
在Java中使用这个@Value(“${ }”)注解 读取 properties中的参数
@Value("${filePath}")
private String filePath;
public void setFilePath(String filePath) {
System.out.println(filePath);
this.filePath = filePath;
}
在其他配置文件中使用 ${ } 读取 properties中的参数
@Component(“fileUpload”)
public class FileUploadUtil implements FileUpload {
@Value("#{PropertiesFactory.filePath}")
private String filePath;
//@Value表示去beans.xml文件中找id="PropertiesFactory"的bean,它是通过注解的方式读取properties配置文件的,然后去相应的配置文件中读取key=filePath的对应的value值
public void setFilePath(String filePath) {
System.out.println(filePath);
this.filePath = filePath;
3.扫描多个配置文件,把需要扫描的文件放在新建的conf文件下:
在D:\Project\tc_vsmp\src-main-resources\applicationContext.xml 文件中配置bean 扫描
classpath:conf/*
java类读取:
public class SMSScheduler {
/**
*
@Autowired
private LoanQueryService service;
/**
*
*/
@Value("#{prop.TIMEDPUSHDAY}")
public String TIMEDPUSHDAY;
/**
*
*/
@Value("#{prop.SMSSCHEDUlER_JINXING_IPHONENUM}")
public String SMSSCHEDUlER_JINXING_IPHONENUM;
在配置文件中读取:
#{prop.SMSSCHEDUlERTIME}
<template>
<el-card>
<el-row :gutter="20" class="header">
<el-col :span="7">
<el-input placeholder="请输入商品名称..." clearable v-model="queryForm.query"></el-input>
</el-col>
<el-button type="primary" :icon="Search" @click="initProductList">搜索</el-button>
<el-button type="primary" @click="handleDialogValue()">添加商品</el-button>
</el-row>
<el-table :data="tableData" stripe style="width: 100%">
<el-table-column prop="name" label="商品名称" width="200" fixed/>
<el-table-column prop="image" label="商品图片" width="150" align="center">
<template v-slot="scope">
<img :src="getServerUrl()+'/image/product/'+scope.row.proPic" width="80" height="80"/>
</template>
</el-table-column>
<el-table-column prop="price" label="商品价格" width="100" />
<el-table-column prop="stock" label="商品库存" width="200" />
<el-table-column prop="type" label="商品类别" width="200" :formatter="typeNameFormatter"/>
<el-table-column prop="hot" label="热卖?" width="100" align="center">
<template v-slot="{row}">
<el-switch v-model="row.hot" @change="hotChangeHandle(row)"></el-switch>
</template>
</el-table-column>
<el-table-column prop="swiper" label="首页幻灯?" width="100" align="center">
<template v-slot="{row}">
<el-switch v-model="row.swiper" @change="swiperChangeHandle(row)"></el-switch>
</template>
</el-table-column>
<el-table-column prop="swiperPic" label="幻灯图片" width="150" align="center">
<template v-slot="scope">
<img :src="getServerUrl()+'/image/swiper/'+scope.row.swiperPic" width="150" height="75"/>
</template>
</el-table-column>
<el-table-column prop="swiperSort" label="幻灯排序" width="150" align="center"/>
<el-table-column prop="description" label="商品描述" width="400"/>
<el-table-column prop="action" label="操作" width="500" fixed="right">
<template v-slot="scope">
<el-button type="success" @click="handleImageDialogValue(scope.row)">更换图片</el-button>
<el-button type="primary" @click="handleDialogValue(scope.row)">幻灯设置</el-button>
<el-button type="primary" :icon="Edit" @click="handleDialogValue(scope.row)"></el-button>
<el-button type="danger" :icon="Delete" @click="handleDelete(scope.row.id)"></el-button>
<el-button type="primary" :icon="Edit" @click="handleDialogValue(scope.row)">轮播图设置</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="queryForm.pageNum"
:page-sizes="[10, 20, 30, 40,50]"
:page-size="queryForm.pageSize"
:small="small"
:disabled="disabled"
:background="background"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</el-card>
<Dialog v-model="dialogVisible" :dialogTitle="dialogTitle" @initProductList="initProductList" :dialogValue="dialogValue"/>
<ImageDialog v-model="imageDialogVisible" :imageDialogValue="imageDialogValue" @initProductList="initProductList"></ImageDialog>
</template>
<script setup>
import {Search,Edit,Delete } from '@element-plus/icons-vue'
import { ref } from 'vue'
import axios,{ getServerUrl } from '@/util/axios'
import Dialog from './components/dialog'
import ImageDialog from './components/imageDialog'
import {ElMessageBox,ElMessage} from 'element-plus'
const queryForm=ref({
query:'',
pageNum:1,
pageSize:10
})
const total=ref(0)
const tableData=ref([
])
const dialogValue=ref({})
const dialogVisible=ref(false)
const dialogTitle=ref('')
const imageDialogVisible=ref(false)
const imageDialogValue=ref({})
const initProductList=async()=>{
console.log('xxx')
const res=await axios.post("admin/product/list",queryForm.value);
tableData.value=res.data.productList;
total.value=res.data.total;
}
initProductList();
const handleSizeChange=(pageSize)=>{
queryForm.value.pageNum=1;
queryForm.value.pageSize=pageSize;
initProductList();
}
const handleCurrentChange=(pageNum)=>{
queryForm.value.pageNum=pageNum;
initProductList();
}
const handleImageDialogValue=(row)=>{
imageDialogValue.value=JSON.parse(JSON.stringify(row))
imageDialogVisible.value=true
}
const handleDialogValue = (row) => {
if(row){
dialogValue.value=JSON.parse(JSON.stringify(row));
dialogTitle.value="商品修改"
}else{
dialogValue.value={
bigType:{
id:""
}
}
dialogTitle.value="商品添加"
}
dialogVisible.value=true;
}
const handleDelete = (id) => {
ElMessageBox.confirm(
'您确定要删除这条记录吗?',
'系统提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async() => {
console.log("id="+id)
let res=await axios.get("admin/product/delete/"+id);
if(res.data.code==0){
ElMessage({
type: 'success',
message: '删除成功!',
});
initProductList();
}else{
ElMessage({
type: 'error',
message: res.data.msg,
});
}
})
.catch(() => {
})
}
const typeNameFormatter=(row)=>{
return row.type.name
}
const hotChangeHandle=async(row)=>{
let res = await axios.get("admin/product/updateHot/"+row.id+"/state/"+row.hot);
if(res.data.code==0){
ElMessage({
type:'success',
message:'执行成功!',
})
}else{
ElMessage({
type: 'error',
message: res.data.msg,
})
initProductList();
}
}
const swiperChangeHandle=async(row)=>{
let res = await axios.get("admin/product/updateSwiper/"+row.id+"/state/"+row.swiper);
if(res.data.code==0){
ElMessage({
type:'success',
message:'执行成功!',
})
}else{
ElMessage({
type: 'error',
message: res.data.msg,
})
initProductList();
}
}
</script>
<style lang="scss" scoped>
.header{
padding-bottom: 16px;
box-sizing: border-box;
}
.el-pagination{
padding-top: 15px;
box-sizing: border-box;
}
</style>
<template>
<el-dialog
model-value="imageDialogVisible"
title="商品图片更换"
width="30%"
@close="handleClose"
center
>
<el-form
ref="formRef"
:model="form"
label-width="100px"
style="text-align: center"
>
<el-upload
:headers="headers"
class="avatar-uploader"
:action="getServerUrl()+'/admin/product/uploadImage'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleConfirm">确认更换</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import {defineEmits, defineProps, ref, watch} from "vue";
import axios,{getServerUrl} from "@/util/axios";
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
const tableData=ref([])
const props=defineProps(
{
imageDialogValue:{
type:Object,
default:()=>{},
required:true
}
}
)
const headers=ref({
token:window.sessionStorage.getItem("token")
})
const form=ref({
id:-1,
proPic:''
})
const formRef=ref(null)
const imageUrl=ref("")
watch(
()=>props.imageDialogValue,
()=>{
form.value=props.imageDialogValue;
imageUrl.value=getServerUrl()+'/image/product/'+form.value.proPic
},
{deep:true,immediate:true}
)
const emits=defineEmits(['update:modelValue','initProductList'])
const handleClose=()=>{
emits('update:modelValue',false)
}
const handleAvatarSuccess=(res)=>{
imageUrl.value=getServerUrl()+res.data.src
form.value.proPic=res.data.title;
}
const beforeAvatarUpload = (file) => {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
ElMessage.error('图片必须是jpg格式')
}
if (!isLt2M) {
ElMessage.error('图片大小不能超过2M!')
}
return isJPG && isLt2M
}
const handleConfirm=async()=>{
let result=await axios.post("admin/product/save",form.value);
let data=result.data;
if(data.code==0){
ElMessage.success("执行成功!")
formRef.value.resetFields();
emits("initProductList")
handleClose();
}else{
ElMessage.error(data.msg);
}
}
</script>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
bigTypeImagesFilePath: D://java1234-mall-v3/bigTypeImgs/
productImagesFilePath: D://java1234-mall-v3/productImgs/