目录
- 服务详情修改优化
- ProductServiceImpl
- Product.vue
- 详情数据-富文本-vue-quill-editor
- 使用步骤
- 测试
- 图片的访问方式
- 富文本集成fastDfs
- 后台服务上下架(批量)
- 前端开始
- 后端完成
- ProductController
- ProductServiceImpl
- ProductMapper
- 前台展示上架
- 前端开始
- 后端完成
- ProductQuery
- ProductController
- ProductMapper
- 测试
- 前端展示列表和图片
- product.html
- 服务高级查询
- 分页
- 查看详情
- 跳转详情页
- 数据展示后台接口
- ProductController
- ProductMapper
- 前台展示
- 导入vue和axios
- 获取数据.js
- 展示数据
- 图片展示
- 详情
- 名称,售价,原价,销量
- 切换图片js
服务详情修改优化
ProductServiceImpl
product后端保存操作修改
@Overridepublic void update(Product product) {ProductDetail detail = product.getDetail();if(detail !=null){if(detail.getId() !=null){productDetailMapper.update(detail);}else{productDetailMapper.save(detail);}}productMapper.update(product);}
Product.vue
显示新增界面清除页面缓存
//显示新增界面handleAdd: function () {this.fileList = [];//清楚页面缓存数据this.productFormVisible = true;//显示新增弹出框this.productForm = {id: null,name: '',resources: '',saleprice: 0,costprice: 0,detail:{id:null,intro:'',orderNotice:''}};},
详情数据-富文本-vue-quill-editor
使用步骤
见文档
测试
图片的访问方式
1.链接访问,
2.页面本地存储二进制字节码,base64加密,长度很长不好保存到数据库,
富文本集成fastDfs
修改页面本地存储为链接存储,步骤见文档
结果:
后台服务上下架(批量)
前端开始
页面加两个按钮,未选置灰,绑定事件,传id数组到后端,
<el-form-item><el-button type="success" @click="onsale" :disabled="this.sels.length===0">上架</el-button>
</el-form-item>
<el-form-item><el-button type="warning" @click="offsale" :disabled="this.sels.length===0">下架</el-button>
</el-form-item>
sels: [],//列表选中行
onsale(){var ids = this.sels.map(item => item.id);//获取选中的行if(!this.sels || this.sels.length <1){this.$message({ message: '老铁,你不选中数据,臣妾上架不了啊....',type: 'error'});return;}this.$confirm('确认上架选中记录吗?', '温馨提示', {type: 'warning'}).then(() => {this.listLoading = true;this.$http.post('/product/onsale',ids).then((res) => {this.listLoading = false;if(res.data.success){this.$message({message: '上架成功',type: 'success'});}else{this.$message({message: res.data.message,type: 'error'});}this.getProducts();});}).catch(() => {});},offsale(){var ids = this.sels.map(item => item.id);//获取选中的行if(!this.sels || this.sels.length <1){this.$message({ message: '老铁,你不选中数据,臣妾下架不了啊....',type: 'error'});return;}this.$confirm('确认下架选中记录吗?', '提示', {type: 'warning'}).then(() => {this.listLoading = true;this.$http.post('/product/offsale',ids).then((res) => {this.listLoading = false;if(res.data.success){this.$message({message: '下架成功',type: 'success'});}else{this.$message({message: res.data.message,type: 'error'});}this.getProducts();});}).catch(() => {});}
后端完成
ProductController
/*** 批量上架*/@PostMapping("/onsale")public AjaxResult onsale(@RequestBody List<Long> ids){try {productService.onOrOffSale(ids,1);//flag:0下架 1上架return AjaxResult.me();} catch (Exception e) {e.printStackTrace();return AjaxResult.me().setMessage("上架失败!"+e.getMessage());}}/*** 批量下架*/@PostMapping("/offsale")public AjaxResult offsale(@RequestBody List<Long> ids){try {productService.onOrOffSale(ids,0);//flag:0下架 1上架return AjaxResult.me();} catch (Exception e) {e.printStackTrace();return AjaxResult.me().setMessage("下架失败!"+e.getMessage());}}
ProductServiceImpl
@Overridepublic void onOrOffSale(List<Long> ids, int flag) {//1.判断是上架还是下架Map<String,Object> map = new HashMap<>();map.put("ids", ids);if(flag == 1){//1.1 调整状态//1.2时间map.put("onSaleTime",new Date());productMapper.onSale(map);}else{//1.1 调整状态//1.2时间map.put("offSaleTime",new Date());productMapper.offSale(map);}}
ProductMapper
<!--void onSale(Map<String, Object> map);--><update id="onSale" >UPDATE t_product set state=1, onsaletime=#{onSaleTime} where id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></update><!--void offSale(Map<String, Object> map);--><update id="offSale" >UPDATE t_product set state=0, offsaletime=#{offSaleTime} where id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></update>
前台展示上架
前端开始
index修改栏目名称,拷贝search为product,修改引入路径,index支持跳转到product,product修改栏目名称并支持跳转到index,
拷贝success为adoutUs,修改引入路径,index支持跳转到adoutUs,adoutUs修改页面内容,
product引入vue和axios,用div包住body里的内容,写vue实例,
后端完成
ProductQuery
@Data
public class ProductQuery extends BaseQuery {//查询上下架的标识private Integer state;
}
ProductController
/*** 前端主站使用的接口,只查询上架的*/@PostMapping("/list")public PageList<Product> queryWebPage(@RequestBody ProductQuery productQuery){productQuery.setState(1);return productService.queryPage(productQuery);}
ProductMapper
<!--Integer queryCount(ProductQuery productQuery);--><select id="queryCount" parameterType="ProductQuery" resultType="integer">SELECT count(*) FROM t_product<include refid="whereSql"/></select><!--List<Product> queryData(ProductQuery productQuery)--><select id="queryData" resultType="Product" parameterType="ProductQuery">SELECT * FROM t_product<include refid="whereSql"/>limit #{start},#{pageSize}</select><!--Where条件--><sql id="whereSql"><where><if test="keyword != null and keyword != ''">AND name LIKE concat("%",#{keyword},"%")</if><if test="state != null">AND state = #{state}</if></where></sql>
测试
注释掉拦截器,然后可以免登录用swagger测试
前端展示列表和图片
调整入参获取数据,遍历,按照规格渲染到页面
fastDfs传800×800可以自定转430×430,350×350,60×60,
product.html
<ul class="am-avg-sm-2 am-avg-md-3 am-avg-lg-4 boxes"><li v-for="product in pageList.rows"><div class="i-pic limit"><img :src="baseFastUrl + product.resources.split(',')[0] + imgSuffix" /><p class="title fl">【官方旗舰店】{{product.name}}</p><p class="price fl"><b>¥</b><strong>{{product.saleprice}}</strong></p><p class="number fl">销量<span>{{product.salecount}}</span></p></div></li>
</ul>
<script type="text/javascript">new Vue({el: "#productDiv",data: {baseFastUrl: "http://115.159.217.249:8888/",imgSuffix: "_350x350.jpg",pageList: {total: 0,rows: []},queryParams: {pageSize: 12,currentPage: 1,keyword: '',}},methods: {getProducts() {this.$http.post("/product/list", this.queryParams).then(result => {result = result.data;//pageList rows totalconsole.log(result);if (result) {this.pageList = result;}}).catch(result => {console.log(result);alert("系统错误!");})}},mounted() {this.getProducts();}})
</script>
服务高级查询
元素绑定
<div class="search-bar pr"><a name="index_none_header_sysc" href="#"></a><form><input id="searchInput" name="index_none_header_sysc" v-model="queryParams.keyword" type="text" placeholder="搜索" autocomplete="off"><input id="ai-topsearch" class="submit am-btn" @click="search" value="搜索" index="1" type="button"></form>
</div>
方法绑定
search() {this.queryParams.currentPage = 1;//定为到第一页this.getProducts();},
分页
页数计算与展示,不同页查询,左右箭头分页查询并限制不超过第一页和最后页,
<!--分页 -->
<ul class="am-pagination am-pagination-right"><!--class="am-disabled"--><li><a href="javascript:;" @click="handCurrentPage(queryParams.currentPage -1)">«</a></li><li v-for="page in countPage"><a href="javascript:;" @click="handCurrentPage(page)">{{page}}</a></li><li><a href="javascript:;" @click="handCurrentPage(queryParams.currentPage +1)">»</a></li>
</ul>
computed: {countPage() {//向上取整return Math.ceil(this.pageList.total / this.queryParams.pageSize);}},
handCurrentPage(page) {//动态分页if (page == 0) {this.queryParams.currentPage = 1;//定位到第一页} else if (page >= this.countPage) {this.queryParams.currentPage = this.countPage;//定位到最后页} else {this.queryParams.currentPage = page;//定位到所选页}this.getProducts();},
查看详情
跳转详情页
<li v-for="product in pageList.rows" @click="goDetail(product.id)">
goDetail(productId) {//跳转到详情页//当前窗体打开//location.href = "http://localhost/productDetail.html?productId=" + productId;window.open("http://localhost/productDetail.html?productId=" + productId);},
数据展示后台接口
ProductController
@GetMapping("/{id}")@ApiOperation(value = "查询一条服务数据",notes = "需要传入id")public Product getById(@PathVariable("id") Long id){return productService.getById(id);}
ProductMapper
<resultMap id="ProductMap" type="Product"><!--基础属性--><id column="id" property="id"/><result column="name" property="name"/><result column="resources" property="resources"/><result column="saleprice" property="saleprice"/><result column="costprice" property="costprice"/><result column="offsaletime" property="offsaletime"/><result column="onsaletime" property="onsaletime"/><result column="state" property="state"/><result column="createtime" property="createtime"/><result column="salecount" property="salecount"/><association property="detail" javaType="ProductDetail"><id column="did" property="id"/><result column="intro" property="intro"/><result column="orderNotice" property="orderNotice"/></association></resultMap><!--Product loadById(Long id);--><select id="loadById" resultMap="ProductMap">SELECTp.*, d.id did,d.intro,d.orderNoticeFROMt_product pLEFT JOIN t_product_detail d ON p.id = d.product_idWHEREp.id = #{id}</select>
前台展示
导入vue和axios
获取数据.js
<script type="text/javascript">new Vue({el:"#productDetailDiv",data:{product:{},fastDfsUrl:"http://115.159.217.249:8888",midimgSuffix:"_350x350.jpg",smallimgSuffix:"_60x60.jpg",resources:[]},mounted(){let productId = parseUrlParams2Obj(location.href).productId;this.$http.get("/product/"+productId).then(result=>{this.product = result.data;if(this.product.resources){this.resources = this.product.resources.split(',');}}).catch(result=>{console.log(result);alert("系统错误");})}});
</script>
展示数据
图片展示
<div class="tb-booth tb-pic tb-s310"><a :href="fastDfsUrl+resources[0]"><img :src="fastDfsUrl+resources[0]+midimgSuffix" alt="细节展示放大镜特效" :rel="fastDfsUrl+resources[0]" class="jqzoom" /></a></div><ul class="tb-thumb" id="thumblist"><li v-for="(resource,index) in resources"><div class="tb-pic tb-s40 tb-selected" v-if="index==0"><a href="#"><img :src="fastDfsUrl+resource+smallimgSuffix" :mid="fastDfsUrl+resource+midimgSuffix" :big="fastDfsUrl+resource"></a></div><div class="tb-pic tb-s40" v-else><a href="#"><img :src="fastDfsUrl+resource+smallimgSuffix" :mid="fastDfsUrl+resource+midimgSuffix" :big="fastDfsUrl+resource"></a></div></li></ul>
详情
<div class="am-tab-panel am-fade am-in am-active"><div class="J_Brand"><div class="attr-list-hd tm-clear"><h4>服务简介:</h4></div><div class="clear"></div><div v-html="product.detail.intro" v-if="product.detail"></div><div class="clear"></div></div><div class="details"><div class="attr-list-hd after-market-hd"><h4>预定须知</h4></div><div class="twlistNews"><div v-html="product.detail.orderNotice" v-if="product.detail"></div></div></div><div class="clear"></div></div>
名称,售价,原价,销量
略
切换图片js
<script type="text/javascript">// 切换图片js$(document).ready(function() {$(".jqzoom").imagezoom();$("#thumblist").on("click","#thumblist li a", function() {$(this).parents("li").addClass("tb-selected").siblings().removeClass("tb-selected");$(".jqzoom").attr('src', $(this).find("img").attr("mid"));$(".jqzoom").attr('rel', $(this).find("img").attr("big"));});/*$("#thumblist li a").click(function() {$(this).parents("li").addClass("tb-selected").siblings().removeClass("tb-selected");$(".jqzoom").attr('src', $(this).find("img").attr("mid"));$(".jqzoom").attr('rel', $(this).find("img").attr("big"));});*/});
</script>