java运费模板设计 | 您所在的位置:网站首页 › 产品运费模板是什么 › java运费模板设计 |
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。 上一个章节,猿人君教会了你如何去设计和实现运费的基础数据——管理和维护承运商信息。今天我们一起来学习,如何实现运费计算的支柱模块——运费模板。 功能概览 运费模板,的出现是为了解决繁杂的商品运费计算问题,它的功能比较复杂,系统需要提供设置默认运费模板功能,也可以新增运费模板,一般而言,运费模板分为系统默认模板和自定义模板两类。 系统的默认模板用于处理未设置运费模板的商品运费计算。 自定义模板,用于计算设置地区的运费计算,其中计费方式支持按计费类型来支持按重量、体积、数量的计费方式(当运费类型为自定义运费时才支持这一选项)。 在列表页面,系统模板不允许新增和修改操作。 数据库设计 基于之前的设计文章猿设计14——真电商之运费模板,我们可以快速地整理运费模板的基本信息,并落地为数据库表,如上图所示。 后端功能实现 运费模板的后台管理功能相对传统,提供新增/修改/停用/启用删除/分页列表的功能。 /** * Copyright(c) 2004-2020 pangzi * com.pz.basic.mall.controller.freight.MallFreightTempleteController.java */package com.pz.basic.mall.controller.freight; import com.pz.basic.mall.domain.base.Result;import com.pz.basic.mall.domain.base.enums.DataStatusEnum;import com.pz.basic.mall.domain.freight.MallFreightTemplete;import com.pz.basic.mall.domain.freight.query.QueryMallFreightTemplete;import com.pz.basic.mall.domain.sys.AreaSelectedVo;import com.pz.basic.mall.service.freight.MallFreightTempleteService;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * * @author pangzi * @date 2020-06-22 20:47:27 * * */@RestController@RequestMapping("/freightTemplete")public class MallFreightTempleteController { private MallFreightTempleteService mallFreightTempleteService; public void setMallFreightTempleteService(MallFreightTempleteService mallFreightTempleteService) { this.mallFreightTempleteService = mallFreightTempleteService; } /** * 新增标准运费 * @param mallFreightTemplete * @return */ @RequestMapping("/addMallFreightTemplete") public Result addMallFreightTemplete(@RequestBody MallFreightTemplete mallFreightTemplete){ try{ return mallFreightTempleteService.addMallFreightTemplete(mallFreightTemplete); }catch(Exception e){ e.printStackTrace(); return new Result(false); } } /** * 根据ID查找标准运费 * @param id * @return */ @RequestMapping("/findMallFreightTempleteById") public Result findMallFreightTempleteById(Long id){ return mallFreightTempleteService.getMallFreightTempleteById(id); } /** * 修改标准运费 * @param mallFreightTemplete * @return */ @RequestMapping("/updateMallFreightTemplete") public Result updateMallFreightTemplete(@RequestBody MallFreightTemplete mallFreightTemplete){ try{ return mallFreightTempleteService.updateMallFreightTempleteById(mallFreightTemplete); }catch(Exception e){ e.printStackTrace(); return new Result(false); } } /** * 启用标准运费 * @param mallFreightTemplete * @return */ @RequestMapping("/enableMallFreightTemplete") public Result enableMallFreightTemplete(@RequestBody MallFreightTemplete mallFreightTemplete){ try{ MallFreightTemplete modifiedData =new MallFreightTemplete (); modifiedData.setTempleteId(mallFreightTemplete.getTempleteId()); modifiedData.setStatus(DataStatusEnum.STATUS_ENABLE.getStatusValue()); return mallFreightTempleteService.updateMallFreightTempleteById(modifiedData); }catch(Exception e){ e.printStackTrace(); return new Result(false); } } /** * 停用标准运费 * @param mallFreightTemplete * @return */ @RequestMapping("/disableMallFreightTemplete") public Result disableMallFreightTemplete(@RequestBody MallFreightTemplete mallFreightTemplete){ try{ MallFreightTemplete modifiedData =new MallFreightTemplete (); modifiedData.setTempleteId(mallFreightTemplete.getTempleteId()); modifiedData.setStatus(DataStatusEnum.STATUS_DISABLE.getStatusValue()); return mallFreightTempleteService.updateMallFreightTempleteById(modifiedData); }catch(Exception e){ e.printStackTrace(); return new Result(false); } } /** * 删除标准运费 * @param mallFreightTemplete * @return */ @RequestMapping("/deleteMallFreightTemplete") public Result deleteMallFreightTemplete(@RequestBody MallFreightTemplete mallFreightTemplete){ try{ MallFreightTemplete modifiedData =new MallFreightTemplete (); modifiedData.setTempleteId(mallFreightTemplete.getTempleteId()); modifiedData.setStatus(DataStatusEnum.STATUS_DELETED.getStatusValue()); return mallFreightTempleteService.updateMallFreightTempleteById(modifiedData); }catch(Exception e){ e.printStackTrace(); return new Result(false); } } /** * 分页返回标准运费列表 * @param queryMallFreightTemplete * @return */ @RequestMapping("/findByPage") public Result> findByPage(@RequestBody QueryMallFreightTemplete queryMallFreightTemplete){ return mallFreightTempleteService.getMallFreightTempletesByPage(queryMallFreightTemplete); } /** * 获取默认运费模板 * @param queryMallFreightTemplete * @return */ @RequestMapping("/findDefaultlFreightTemplete") public Result findDefaultlFreightTemplete(@RequestBody QueryMallFreightTemplete queryMallFreightTemplete){ return mallFreightTempleteService.findDefaultlFreightTemplete(queryMallFreightTemplete); } @RequestMapping("/selectForFreightTemplete") public Result> selectForFreightTemplete(@RequestBody QueryMallFreightTemplete queryMallFreightTemplete){ return mallFreightTempleteService.selectForFreightTemplete(queryMallFreightTemplete); } } 考虑到很多朋友编写mapper文件比较困难,这个章节的mapper就先给到你吧,不过做人不要太懒了,domain 和dao 以及service的实现,还是自己动手搞一下吧。 templete_id,templete_name,logistics_code,logistics_name,templete_type,service_type,freight_type,charge_type,num_min,num_max,frist_num_price,next_num_price,weight_min,weight_max,frist_weight_price,next_weight_price,volume_min,volume_max,frist_volume_price,next_volume_price,status,create_user,modify_user,created,modifiedstatus>-1and templete_id = #{templeteId}and templete_name = #{templeteName}and logistics_code = #{logisticsCode}and logistics_name = #{logisticsName}and templete_type = #{templeteType}and service_type = #{serviceType}and freight_type = #{freightType}and charge_type = #{chargeType}and num_min = #{numMin}and num_max = #{numMax}and frist_num_price = #{fristNumPrice}and next_num_price = #{nextNumPrice}and weight_min = #{weightMin}and weight_max = #{weightMax}and frist_weight_price = #{fristWeightPrice}and next_weight_price = #{nextWeightPrice}and volume_min = #{volumeMin}and volume_max = #{volumeMax}and frist_volume_price = #{fristVolumePrice}and next_volume_price = #{nextVolumePrice}and status = #{status}and create_user = #{createUser}and modify_user = #{modifyUser}and created = #{created}and modified = #{modified}selectfrom mall_freight_templeteselectfrom mall_freight_templeteLIMIT #{startRow},#{pageSize}selectfrom mall_freight_templetewhere templete_id = #{templeteId}delete from mall_freight_templetewhere templete_id = #{templeteId}delete from mall_freight_templeteINSERT INTOmall_freight_templete(templete_id,templete_name,logistics_code,logistics_name,templete_type,service_type,freight_type,charge_type,num_min,num_max,frist_num_price,next_num_price,weight_min,weight_max,frist_weight_price,next_weight_price,volume_min,volume_max,frist_volume_price,next_volume_price,status,create_user,modify_user,created,modified)VALUES(#{templeteId},#{templeteName},#{logisticsCode},#{logisticsName},#{templeteType},#{serviceType},#{freightType},#{chargeType},#{numMin},#{numMax},#{fristNumPrice},#{nextNumPrice},#{weightMin},#{weightMax},#{fristWeightPrice},#{nextWeightPrice},#{volumeMin},#{volumeMax},#{fristVolumePrice},#{nextVolumePrice},#{status},#{createUser},#{modifyUser},#{created},#{modified})SELECT @@IDENTITY AS IDinsert into mall_freight_templetetemplete_id,templete_name,logistics_code,logistics_name,templete_type,service_type,freight_type,charge_type,num_min,num_max,frist_num_price,next_num_price,weight_min,weight_max,frist_weight_price,next_weight_price,volume_min,volume_max,frist_volume_price,next_volume_price,status,create_user,modify_user,created,modified,#{templeteId},#{templeteName},#{logisticsCode},#{logisticsName},#{templeteType},#{serviceType},#{freightType},#{chargeType},#{numMin},#{numMax},#{fristNumPrice},#{nextNumPrice},#{weightMin},#{weightMax},#{fristWeightPrice},#{nextWeightPrice},#{volumeMin},#{volumeMax},#{fristVolumePrice},#{nextVolumePrice},#{status},#{createUser},#{modifyUser},now(),now(),SELECT @@IDENTITY AS IDselect count(*) from mall_freight_templeteupdate mall_freight_templetetemplete_name = #{templeteName},logistics_code = #{logisticsCode},logistics_name = #{logisticsName},templete_type = #{templeteType},service_type = #{serviceType},freight_type = #{freightType},charge_type = #{chargeType},num_min = #{numMin},num_max = #{numMax},frist_num_price = #{fristNumPrice},next_num_price = #{nextNumPrice},weight_min = #{weightMin},weight_max = #{weightMax},frist_weight_price = #{fristWeightPrice},next_weight_price = #{nextWeightPrice},volume_min = #{volumeMin},volume_max = #{volumeMax},frist_volume_price = #{fristVolumePrice},next_volume_price = #{nextVolumePrice},status = #{status},create_user = #{createUser},modify_user = #{modifyUser},created = #{created},modified=now(),where templete_id = #{templeteId} id,templete_id,privince_id,city_id,area_id,status,create_user,modify_user,created,modified1=1and id = #{id}and templete_id = #{templeteId}and privince_id = #{privinceId}and city_id = #{cityId}and area_id = #{areaId}and status = #{status}and create_user = #{createUser}and modify_user = #{modifyUser}and created = #{created}and modified = #{modified}id = #{id},templete_id = #{templeteId},privince_id = #{privinceId},city_id = #{cityId},area_id = #{areaId},status = #{status},create_user = #{createUser},modify_user = #{modifyUser},created = #{created},modified = #{modified},selectfrom mall_freight_templete_areaselectfrom mall_freight_templete_areaLIMIT #{startRow},#{pageSize}selectfrom mall_freight_templete_areawhere id = #{id}delete from mall_freight_templete_areawhere id = #{id}delete from mall_freight_templete_areaINSERT INTOmall_freight_templete_area(id,templete_id,privince_id,city_id,area_id,status,create_user,modify_user,created,modified)VALUES(#{id},#{templeteId},#{privinceId},#{cityId},#{areaId},#{status},#{createUser},#{modifyUser},#{created},#{modified})SELECT @@IDENTITY AS IDinsert into mall_freight_templete_areaid,templete_id,privince_id,city_id,area_id,status,create_user,modify_user,created,modified,#{id},#{templeteId},#{privinceId},#{cityId},#{areaId},#{status},#{createUser},#{modifyUser},now(),now(),SELECT @@IDENTITY AS IDselect count(*) from mall_freight_templete_areaupdate mall_freight_templete_areatemplete_id = #{templeteId},privince_id = #{privinceId},city_id = #{cityId},area_id = #{areaId},status = #{status},create_user = #{createUser},modify_user = #{modifyUser},created = #{created},modified=now(),where id = #{id} 前端功能实现 功能的实现,主要还是基于element-ui来实现的。这里提几个关键的点,最后也会把源代码给到你的。 列表展示: 主要是通过el-table组件实现的,属性data用于绑定需要展现的数据。需要你定义和操作。 页面数据展示的控制,需要使用v-if指令判断,展示不同的内容 新增/编辑弹框 弹框展示的标题和展示,通过页面定义的数据来控制。 表单中的下拉选项,通过el-select组件来实现。 注意使用的v-for指令,以及你需要在页面上定义你的选项数据。 不同计费方式的动态选择,记得使用v-if指令来进行判断,不同的计费类型,会展示不同的内容。 关键点已经都告诉你一些了,地区设置又是怎么一回事儿呢?不好好看看源码,自己动手去实现一次,比什么都强。 查询 设置默认模板 新增 v-loading="listLoading" :data="list" element-loading-text="Loading" style="width: 100%" border > {{ scope.row.templeteName }} {{ scope.row.logisticsName }} {{ scope.row.logisticsCode }} {{ scope.row.templeteType==1?'系统默认':'自定义' }} 经济服务 快递服务 标准服务 {{ scope.row.freightType==2?'免邮':'按模板计算' }} 按数量 按重量 按体积 {{ scope.row.numMin }} {{ scope.row.weightMin }} {{ scope.row.volumeMin }} {{ scope.row.numMax }} {{ scope.row.weightMax }} {{ scope.row.volumeMax }} {{ scope.row.fristNumPrice }} {{ scope.row.fristWeightPrice }} {{ scope.row.fristVolumePrice }} {{ scope.row.nextNumPrice }} {{ scope.row.nextWeightPrice }} {{ scope.row.nextVolumePrice }} v-if="scope.row.templeteType==2" type="primary" size="mini" @click="handleUpdate(scope.row)" >编辑 v-if="scope.row.status==1 && scope.row.templeteType==2" type="primary" size="mini" @click="handleDisable(scope.$index, scope.row)" >停用 v-if="scope.row.status==0 && scope.row.templeteType==2" type="primary" size="mini" @click="handleEnable(scope.$index, scope.row)" >启用 size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)" >删除 v-for="item in logisticsList" :key="item.id" :label="item.logisticsName" :value="item.logisticsCode" /> v-for="(item,index) in serviceTypeList" :key="index" :label="item.name" :value="item.code" /> v-for="(item,index) in freightTypeList" :key="index" :label="item.name" :value="item.code" /> v-for="(item,index) in chargeTypeList" :key="index" :label="item.name" :value="item.code" /> v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.code" /> 设置地区 ref="tree" :data="areaList" show-checkbox node-key="id" :default-expanded-keys="[1,2]" :default-checked-keys="defaultSelectedArea" clearable filterable allow-create @check-change="updateKeyChildren" /> 取消 确定 import { getLogisticsList, getDefaultTemplete, getFreightTempleteList, selectForFreightTemplete, createFreightTemplete, updateFreightTemplete, enableFreightTemplete, disableFreightTemplete, deleteFreightTemplete } from '@/api/freightManage/carrier' import Pagination from '@/components/Pagination' // secondary package based on el-pagination export default { components: { Pagination }, data() { return { listLoading: false, rules: { logisticsName: [{ required: true, message: '请输入供应商名称', trigger: 'change' }], logisticsCode: [{ required: true, message: '请输入供应商编码', trigger: 'change' }], templeteName: [{ required: true, message: '请输入模板名称', trigger: 'change' }] }, areaList: [], selectedArea: [], defaultSelectedArea: [], listQuery: { page: 1, pageSize: 10 }, listLogisticsQuery: { page: 1, pageSize: 500 }, defaultObjQuery: { page: 1, pageSize: 1 }, areaQuery: { page: 1, pageSize: 1 }, temp: { id: undefined, // 物流供应商编码 logisticsCode: '', // 物流供应商名称L logisticsName: '', serviceType: 3, freightType: 2, chargeType: 1, numMin: 1, numMax: 1, fristNumPrice: 1, nextNumPrice: 1, weightMin: 1, weightMax: 2, fristWeightPrice: 1, nextWeightPrice: 1, volumeMin: 1, volumeMax: 1, fristVolumePrice: 1, nextVolumePrice: 1, status: 1 }, defaultObj: null, logisticsList: [], dialogStatus: '', textMap: { update: '编辑运费模板', create: '新增运费模板', setDefault: '设置默认模板' }, dialogImageUrl: '', dialogVisible: false, // 弹框是否显示 dialogFormVisible: false, dialogAreaVisible: false, // 分页 total: 0, // table集合 list: null, statusList: [ { code: 1, name: '启用' }, { code: 2, name: '停用' } ], chargeTypeList: [ { code: 1, name: '按数量' }, { code: 2, name: '按重量' }, { code: 3, name: '按体积' } ], serviceTypeList: [ { code: 1, name: '经济服务' }, { code: 2, name: '快递服务' }, { code: 3, name: '标准服务' } ], freightTypeList: [ { code: 1, name: '自定义运费' }, { code: 2, name: '卖家承担运费' } ] } }, created() { this.getList() this.getLogisticsList() this.findDefaultTemplete() this.initAreaList() }, methods: { saveData() { if (this.dialogStatus === 'setDefault') { if (undefined === this.temp.templeteId) { this.createData() return } else { this.updateData() return } } else if (this.dialogStatus === 'create') { this.createData() return } else { this.updateData() return } }, // 更新保存方法 updateData() { this.$refs['dataForm'].validate((valid) => { if (valid) { const tempData = Object.assign({}, this.temp) updateFreightTemplete(tempData).then(() => { const index = this.list.findIndex(v => v.id === this.temp.id) this.list.splice(index, 1, this.temp) this.dialogFormVisible = false this.$notify({ title: 'Success', message: 'Update Successfully', type: 'success', duration: 2000 }) }) } }) }, // 创建保存方法 createData() { this.$refs['dataForm'].validate((valid) => { if (valid) { createFreightTemplete(this.temp).then((res) => { this.temp.id = res.model.id this.list.unshift(this.temp) this.dialogFormVisible = false this.$notify({ title: 'Success', message: 'Created Successfully', type: 'success', duration: 2000 }) }) } }) }, // 编辑 handleUpdate(row) { this.temp = Object.assign({}, row) // copy obj this.dialogStatus = 'update' this.dialogFormVisible = true this.areaQuery.templeteId = this.temp.templeteId this.initAreaList() this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) }, // 启用 handleEnable(index, row) { enableFreightTemplete(Object.assign({}, row)).then((res) => { this.$notify({ title: 'Success', message: 'Created Successfully', type: 'success', duration: 2000 }) this.getList() }) }, // 停用 handleDisable(index, row) { disableFreightTemplete(row).then((res) => { this.$notify({ title: 'Success', message: 'Created Successfully', type: 'success', duration: 2000 }) this.getList() }) }, // 删除 handleDelete(index, row) { deleteFreightTemplete(row).then((res) => { this.$notify({ title: 'Success', message: 'Created Successfully', type: 'success', duration: 2000 }) this.getList() }) }, resetTemp() { this.temp = { id: undefined, // 物流供应商编码 logisticsCode: '', // 物流供应商名称L logisticsName: '', serviceType: 3, templeteType: 2, freightType: 2, chargeType: 1, numMin: 1, numMax: 1, fristNumPrice: 1, nextNumPrice: 1, weightMin: 1, weightMax: 2, fristWeightPrice: 1, nextWeightPrice: 1, volumeMin: 1, volumeMax: 1, fristVolumePrice: 1, nextVolumePrice: 1, status: 1 } }, // 新增 addFreightTemplete() { this.resetTemp() this.dialogStatus = 'create' this.dialogFormVisible = true this.areaQuery.templeteId = null this.initAreaList() this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) }, setDefaultTemplete() { if (undefined !== this.defaultObj && this.defaultObj !== null) { this.temp = this.defaultObj this.areaQuery.templeteId = null } else { this.resetTemp() this.temp.templeteType = 1 } this.dialogStatus = 'setDefault' this.dialogFormVisible = true this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) }, // 查询方法 fetchData() { this.listQuery.page = 1 this.listQuery.pageSize = 10 // this.listQuery.limit = 10 this.getList() }, // 重置表单 resetForm(formName) { this.$refs[formName].resetFields() }, // 列表方法查询 getList() { this.listLoading = true getFreightTempleteList(this.listQuery).then(response => { this.list = response.model this.total = response.totalItem // Just to simulate the time of the request setTimeout(() => { this.listLoading = false }, 1.5 * 1000) }) }, getLogisticsList() { this.listLoading = true getLogisticsList(this.listLogisticsQuery).then(response => { this.logisticsList = response.model }) setTimeout(() => { this.listLoading = false }, 1.5 * 1000) }, initAreaList() { this.defaultSelectedArea = [] selectForFreightTemplete(this.areaQuery).then(response => { var tempList = response.model if (undefined !== tempList && tempList != null) { for (let i = 0; i < tempList.length; i++) { for (let j = 0; j < tempList[i].children.length; j++) { if (tempList[i].children[j].checkStatus === 1) { this.defaultSelectedArea.push(tempList[i].children[j].id) } } } } this.areaList = tempList }) console.log(this.defaultSelectedArea) }, findDefaultTemplete() { this.listLoading = true getDefaultTemplete(this.defaultObjQuery).then(response => { this.defaultObj = response.model }) setTimeout(() => { this.listLoading = false }, 1.5 * 1000) }, selectLogistics(option) { let selectedItem = {} selectedItem = this.logisticsList.find((item) => { return item.logisticsCode === option }) this.temp.logisticsCode = option if (undefined !== selectedItem) { this.temp.logisticsName = selectedItem.logisticsName } else { this.logisticsName = '' } }, changeChargeType(option) { if (option === 1) { this.temp.weightMin = 0 this.temp.weightMax = 0 this.temp.fristWeightPrice = 0 this.temp.nextWeightPrice = 0 this.temp.volumeMin = 0 this.temp.volumeMax = 0 this.temp.fristVolumePrice = 0 this.temp.nextVolumePrice = 0 } if (option === 2) { this.temp.numMin = 0 this.temp.numMax = 0 this.temp.fristNumPrice = 0 this.temp.nextNumPrice = 0 this.temp.volumeMin = 0 this.temp.volumeMax = 0 this.temp.fristVolumePrice = 0 this.temp.nextWeightPrice = 0 } if (option === 3) { this.temp.numMin = 0 this.temp.numMax = 0 this.temp.fristNumPrice = 0 this.temp.nextNumPrice = 0 this.temp.weightMin = 0 this.temp.weightMax = 0 this.temp.fristWeightPrice = 0 this.temp.nextWeightPrice = 0 } }, updateKeyChildren(data, key1, key2) { const checkedNodes = this.$refs.tree.getCheckedNodes() if (checkedNodes != null && checkedNodes.length > 0) { for (let i = 0; i < checkedNodes.length; i++) { var area = { id: undefined, parentId: undefined, label: '', level: 1 } area.id = checkedNodes[i].id area.label = checkedNodes[i].label area.level = checkedNodes[i].level if (undefined !== checkedNodes[i].parentId && checkedNodes[i].parentId !== null) { area.parentId = checkedNodes[i].parentId } this.selectedArea.push(area) this.temp.selectedArea = this.selectedArea } } }, setArea() { this.dialogAreaVisible = !this.dialogAreaVisible } } } a, a:focus, a:hover { cursor: pointer; color: rgb(67, 149, 255); text-decoration: none; margin: 10px; } |
CopyRight 2018-2019 实验室设备网 版权所有 |