一、维修单业务模块分析
1、业务逻辑:
–>对来维修车辆进行登记;
—>接待人员填写维修单基本信息:分配维修人员;
—>维修人员填写维修明细:包括配件及价格等;
—>维修完成结算。
二、svn导出项目
后端结构:
前端结构:
三、数据库表以及domain创建
1、domain与query在同一个模块,且没有spring配置文件:
2、维修单(一对多):
public class RepairOrder extends BaseDomain {
//1、客户姓名:页面录入
private String customer;
//2、车牌号:车管所登记车牌号
private String carnum;
//3、维修单创建时间:录入之后自动生成
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//前端传过来的日期转换
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")//后端查询出来传回前端的日期转换
private Date createTime=new Date();
//4、状态:1已录入,2已结算,保存时默认为已录入
private Integer status = 1;
//5、客户地址:结算完之后还车的线路
private String address;
//6、维修人员编号:通过页面分配维修人员
private Maintain maintain;
//7、维修单明细,一对多
private List<RepairOrderItem> repairOrderItems;
2、维修单明细(多对一,只存外键):
public class RepairOrderItem extends BaseDomain {
//配件价格
private BigDecimal amt1;
//配件数量
private Integer num;
//工时费
private BigDecimal amt2;
//总金额
private BigDecimal totalamt;
//维修员
private Maintain maintain;
//维修配件
private CarComponent carComponent;
//维修单号
private Long rep_id;
四、mapper层创建
1、模块结构:
2、sql语句:
(1)维修工单:
<?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="cn.itsource.group1.mapper.RepairOrderMapper">
<!--1、查询所有维修单-->
<!--List<T> loadAll();-->
<select id="loadAll" resultMap="RepairOrderMap">
select * from t_repairorder
</select>
<!--维修单数据库表的列与类的相应字段配置,映射-->
<resultMap id="RepairOrderMap" type="cn.itsource.group1.domain.RepairOrder">
<id property="id" column="id" />
<result property="customer" column="customer" />
<result property="carnum" column="carnum" />
<result property="createTime" column="createTime" />
<result property="status" column="status" />
<result property="address" column="address" />
<!--配置维修员信息-1.1-->
<association property="maintain" column="opt_id" select="findMaintainById"
javaType="cn.itsource.group1.domain.Maintain">
</association>
<!--配置明细的集合-1.2-->
<!--调用明细RepairOrderItem 的mapper.xml里的select语句-->
<collection property="repairOrderItems" column="id"
select="cn.itsource.group1.mapper.RepairOrderItemMapper.loadByRepId"
ofType="cn.itsource.group1.domain.RepairOrderItem" >
</collection>
</resultMap>
<!--嵌套查询维修员-1.1-->
<select id="findMaintainById" parameterType="long"
resultType="cn.itsource.group1.domain.Maintain">
select * from t_maintain where id = #{opt_id}
</select>
<!--2、保存-->
<!--void save(T t);-->
<insert id="save" parameterType="RepairOrder" useGeneratedKeys="true" keyColumn="id" keyProperty="long">
insert into t_repairorder(customer,carnum,createTime,status,address,opt_id)
values(#{customer},#{carnum},#{createTime},#{status},#{address},#{maintain.id})
</insert>
<!--3、更新-->
<!--void update(T t);-->
<!--if标签拼接:先判断字段是否为空,再进行修改-->
<update id="update" parameterType="RepairOrder">
update t_repairorder
<set>
<if test="customer!=null">
customer=#{customer},
</if>
<if test="maintain!=null and maintain.id!=null">
opt_id=#{maintain.id},
</if>
<if test="carnum!=null">
carnum=#{carnum},
</if>
<if test="status!=null">
status=#{status},
</if>
<if test="address!=null">
address=#{address},
</if>
</set>
where id=#{id}
</update>
<!--4、根据 id 删除-->
<!--void remove(Serializable id);-->
<delete id="remove" parameterType="long">
delete from t_repairorder where id = #{id}
</delete>
<!--5、根据 id 查询一个-->
<!--T loadById(Serializable id);-->
<select id="loadById" parameterType="long" resultMap="RepairOrderMap">
select * from t_repairorder where id = #{id}
</select>
<!--6、查询数据总条数-->
<select id="queryCount" parameterType="RepairOrderQuery" resultType="long">
select count(*) from t_repairorder
<if test="keywords != null and keywords !=''">
where carnum like concat('%',#{keywords},'%')
</if>
</select>
<!--7、查询当前页数据-->
<select id="queryData" parameterType="RepairOrderQuery" resultMap="RepairOrderMap">
select * from t_repairorder
<if test="keywords != null and keywords !=''">
where carnum like concat('%',#{keywords},'%')
</if>
order by createTime desc limit #{start},#{pageSize}
</select>
</mapper>
(2)维修明细:
<?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="cn.itsource.group1.mapper.RepairOrderItemMapper">
<!--1、查询所有明细单-->
<!--List<T> loadAll();-->
<select id="loadAll" resultMap="RepairOrderItemMap">
select * from t_repairorderitem
</select>
<!--明细:数据库表的列 与 类的相应字段 配置,映射-->
<resultMap id="RepairOrderItemMap" type="cn.itsource.group1.domain.RepairOrderItem">
<!--明细编号,主键-->
<id property="id" column="id" />
<!--所属维修单编号-->
<result property="rep_id" column="rep_id" />
<!--配件价格-->
<result property="amt1" column="amt1" />
<!--工时费-->
<result property="amt2" column="amt2" />
<!--配件数量-->
<result property="num" column="num" />
<!--总金额-->
<result property="totalamt" column="totalamt" />
<!--配置维修员信息-1.1-->
<association property="maintain" column="op_id" select="findMaintainById"
javaType="cn.itsource.group1.domain.Maintain">
</association>
<!--配置配件信息-1.2-->
<association property="carComponent" column="p_id" select="findCarComponentById"
javaType="cn.itsource.group1.domain.CarComponent">
</association>
</resultMap>
<!--嵌套查询维修员-1.1-->
<select id="findMaintainById" parameterType="long"
resultType="cn.itsource.group1.domain.Maintain">
select * from t_maintain where id = #{id}
</select>
<!--嵌套查询配件-1.2-->
<select id="findCarComponentById" parameterType="long"
resultType="cn.itsource.group1.domain.CarComponent">
select * from t_carcomponent where id = #{id}
</select>
<!--2、保存-->
<!--void save(T t);-->
<!--回显主键id-->
<insert id="save" parameterType="RepairOrderItem" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
>
insert into t_repairorderitem(rep_id,op_id,p_id,amt1,amt2,num,totalamt)
values(#{rep_id},#{maintain.id},#{carComponent.id},#{amt1},#{amt2},#{num},#{totalamt})
</insert>
<!--3、修改-->
<!--void update(T t);-->
<!--if标签拼接:先判断字段是否为空,再进行修改-->
<update id="update" parameterType="RepairOrderItem">
update t_repairorderitem
<set>
<if test="rep_id!=null">
rep_id=#{rep_id},
</if>
<if test="maintain!=null and maintain.id!=null">
op_id=#{maintain.id},
</if>
<if test="carComponent!=null and carComponent.id!=null">
p_id=#{carComponent.id},
</if>
<if test="amt1!=null">
amt1=#{amt1},
</if>
<if test="amt2!=null">
amt2=#{amt2},
</if>
<if test="num!=null">
num=#{num},
</if>
<if test="totalamt!=null">
totalamt=#{totalamt},
</if>
</set>
where id=#{id}
</update>
<!--4、根据 id 删除一条明细-->
<!--void remove(Serializable id);-->
<delete id="remove" parameterType="long">
delete from t_repairorderitem where id = #{id}
</delete>
<!--5、根据 维修单号 rep_id,删除关联的明细-->
<!--void remove(Serializable id);-->
<delete id="removeByRepid" parameterType="long">
delete from t_repairorderitem where rep_id = #{rep_id}
</delete>
<!--6、根据 id 查询一个明细-->
<!--T loadById(Serializable id);-->
<select id="loadById" parameterType="long" resultMap="RepairOrderItemMap">
select * from t_repairorderitem where id = #{id}
</select>
<!--7、根据 订单编号,rep_id 查询相关明细-->
<!--T loadById(Serializable id);-->
<select id="loadByRepId" parameterType="long" resultMap="RepairOrderItemMap">
select * from t_repairorderitem where rep_id = #{id}
</select>
<!--8、查询数据总条数-->
<select id="queryCount" parameterType="RepairOrderItemQuery" resultType="long">
select count(*) from t_repairorderitem
where rep_id=#{rep_id}
</select>
<!--9、根据 订单编号,rep_id 查询相关明细分页-->
<select id="queryData" parameterType="RepairOrderItemQuery" resultMap="RepairOrderItemMap">
select * from t_repairorderitem
where rep_id=#{rep_id}
order by totalamt limit #{start},#{pageSize}
</select>
</mapper>
五、service层创建(代码省略)
六、controller层创建
1、跨域分类:
(1)域名不同 :如 www.jd.com 与 www.taobao.com
(2)域名相同,端口不同:如www.jd.com:8080 与 www.jd.com:8081
(3)二级域名不同:如 item.jd.com 与 miaosha.jd.com
2、跨域解决:
最佳方案,注解:@CrossOrigin
3、模块结构:
4、维修单java代码:
@Controller
@RequestMapping("/repairorder")
//支持跨域访问
@CrossOrigin
public class RepairOrderController {
@Autowired
private IRepairOrderService repairOrderService;
@Autowired
private IRepairOrderItemService repairOrderItemService;
//@Override
@ResponseBody
@RequestMapping(value = "/edit",method = RequestMethod.PUT)
//1、添加或修改
public AjaxResult addOrUpdate(@RequestBody RepairOrder repairOrder) {
//id存在时,进行修改
if (repairOrder.getId()!=null&&repairOrder.getId()!=0){
try {
repairOrderService.update(repairOrder);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("修改失败");
}
}else {//没有id时,进行添加
try {
repairOrderService.add(repairOrder);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("添加失败");
}
}
return AjaxResult.me();
}
//@Override
@ResponseBody
@RequestMapping(value ="{id}",method = RequestMethod.DELETE)
//2、删除
public AjaxResult del(@PathVariable("id") Long id) {
try {
//删除明细
repairOrderItemService.removeByRepid(id);
//删除维修单
repairOrderService.delete(id);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("删除失败");
}
return AjaxResult.me();
}
//@Override
@ResponseBody
@RequestMapping(value ="{id}",method = RequestMethod.GET)
//3、查询一条
public RepairOrder getOneById(@PathVariable("id") Long id) {
RepairOrder repairOrder =null;
try {
repairOrder = repairOrderService.getById(id);
} catch (Exception e) {
e.printStackTrace();
}
return repairOrder;
}
//@Override
@ResponseBody
@RequestMapping(method = RequestMethod.PATCH)
//4、查询所有
public List<RepairOrder> list() {
List<RepairOrder> repairOrderList =null;
try {
repairOrderList = repairOrderService.getAll();
for (RepairOrder repairOrder : repairOrderList) {
}
} catch (Exception e) {
e.printStackTrace();
}
return repairOrderList;
}
//@Override
@ResponseBody
@RequestMapping(value="/query",method = RequestMethod.POST)
//5、分页高级查询
public PageList<RepairOrder> query(@RequestBody RepairOrderQuery repairOrderQuery) {
PageList<RepairOrder> pageList =null;
try {
pageList = repairOrderService.query(repairOrderQuery);
for (RepairOrder row : pageList.getRows()) {
}
} catch (Exception e) {
e.printStackTrace();
}
return pageList;
}
//6、批量删除
@ResponseBody
@RequestMapping(value ="/deletes",method = RequestMethod.PATCH)
public AjaxResult patchDelete(@RequestBody List<RepairOrder> repairOrders) {
try {
for (RepairOrder repairOrder : repairOrders) {
//删除维修单
repairOrderService.delete(repairOrder.getId());
//删除明细
repairOrderItemService.removeByRepid(repairOrder.getId());
}
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("删除失败");
}
return AjaxResult.me();
}
}
七、elementUI前台页面创建
1、技术:
(1)ElementUI:
问题:
a、验证bug有点多。。。
b、下拉框bug更多。。。
(2)百度地图:
a、百度官网:javascAPI
http://lbsyun.baidu.com/index.php?title=jspopular3.0
2、代码:
<template>
<div>
<!--+++++++++++++++++++++++++++++++++++++++++++++++++++1、维修单栏++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<section>
<!--维修单上方工具条-->
<el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
<el-form :inline="true" :model="filters">
<el-form-item>
<el-input v-model="filters.carnum" placeholder="车牌号"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="queryRepairorders">查询</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
</el-col>
<!--维修单展示列表-->
<el-table :data="repairorders" highlight-current-row v-loading="listLoading"
@selection-change="selsChange" style="width: 100%;" @row-dblclick="showItems">
<el-table-column type="selection" width="55" >
</el-table-column>
<el-table-column prop="customer" label="客户姓名" min-width="10%">
</el-table-column>
<el-table-column prop="carnum" label="车牌号" min-width="12%">
</el-table-column>
<el-table-column prop="createTime" label="录入时间" min-width="17%">
</el-table-column>
<el-table-column prop="address" label="还车地址" min-width="28%">
</el-table-column>
<el-table-column prop="maintain.optName" label="维修员" min-width="8%">
</el-table-column>
<!--状态值转换,颜色转换-->
<el-table-column prop="status" label="状态" min-width="8%">
<template slot-scope="scope">
<!--<p v-html='scope.row.status' v-if="scope.row.status==0" style="color: red"></p>
<p v-html='scope.row.status' v-else="" style="color: green"></p>-->
<span v-if="scope.row.status==1" style="color: red">已录入</span>
<span v-else="" style="color: green">已结算</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="17%">
<template scope="scope">
<el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--维修单下方工具条-->
<el-col :span="24" class="toolbar">
<el-button type="danger" @click="batchRemove" :disabled="this.sels.length===0">批量删除</el-button>
<!--分页栏-->
<el-pagination layout="total,prev, pager, next" @current-change="handleCurrentChange" :page-size="5" :total="total" style="float:right;">
</el-pagination>
</el-col>
<!--编辑界面-->
<!--:visible.sync="repairorderFormVisible" :close-on-click-modal="false" :append-to-body="true"-->
<el-dialog title="编辑" v-model="repairorderFormVisible" :close-on-click-modal="false">
<el-form :model="repairorder" label-width="80px" :rules="editFormRules" ref="editForm">
<el-form-item label="客户姓名" prop="customer">
<el-input style="width:400px" v-model="repairorder.customer" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="车牌号" prop="carnum">
<el-input style="width: 400px" v-model="repairorder.carnum" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="还车地址" prop="address">
<el-input style="width: 400px" v-model="repairorder.address" auto-complete="off"></el-input>
<el-button size="small" type="primary" @click="selectAdrress">选择</el-button>
</el-form-item>
<el-form-item label="维修员" prop="maintainId">
<el-select v-model="repairorder.maintain.id" placeholder="请选择">
<!--钩子mounted 方法中,Ajax查找维修员信息 maintainlist,-->
<el-option v-for="item in maintainlist" :key="item.id"
:label="item.optName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="repairorderFormVisible = false">取消</el-button>
<el-button type="primary" @click.native="editSubmit" >提交</el-button>
</div>
</el-dialog>
<!--百度地图-->
<!--:visible.sync="mapdialogVisible"-->
<el-dialog
title="选择地址" v-model="mapdialogVisible" :close-on-click-modal="false"
width="50%">
<baidu-map :center="{lng: 104.06, lat: 30.67}" :zoom="11">
<bm-view class="map"></bm-view>
<bm-control :offset="{width:'10px', height:'10px'}">
<!--:sugStyle="{zIndex: 2100} 让搜索提示上浮-->
<bm-auto-complete v-model="keyword" :sugStyle="{zIndex:2100}">
<div style="margin-bottom:10px">
<input id="searchInput" type="text" placeholder="请输入关键字" class="searchinput"/>
<el-button type="success" @click="selectAdrressConfirm">确定</el-button>
</div>
</bm-auto-complete>
</bm-control>
<bm-local-search :keyword="keyword" :auto-viewport="true" ></bm-local-search>
</baidu-map>
<span slot="footer" class="dialog-footer">
<el-button @click="mapdialogVisible=false">取 消</el-button>
<el-button type="primary" @click="selectAdrressConfirm">确 定</el-button>
</span>
</el-dialog>
</section>
<!--++++++++++++++++++++++++++++++++++++++++++++++++++++2、明细栏++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<section>
<!--明细上方工具条-->
<el-col :span="15" class="itemtoolbar" style="padding-bottom: 0px;">
<el-form :inline="true" >
<el-form-item>
<el-button type="primary" @click="itemhandleAdd">新增明细</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="setted" style="background-color: orange">结算</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="9" class="itemtoolbar" style="padding-bottom: 0px;">
<span style="font-size: 18px;color: #e64242;">维修车辆(双击选中):</span>
<span v-model="rep_carnum" style="font-size: 18px;color: #1d8ce0" width="50px">{{rep_carnum}}</span>
</el-col>
<!--明细展示列表-->
<el-table :data="repairorderitems" highlight-current-row v-loading="itemlistLoading"
@selection-change="itemselsChange" style="width: 100%;">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column prop="carComponent.partsName" label="配件名" sortable>
</el-table-column>
<el-table-column prop="amt1" label="配件价格" sortable>
</el-table-column>
<el-table-column prop="num" label="配件数量" sortable>
</el-table-column>
<el-table-column prop="amt2" label="工时费" sortable>
</el-table-column>
<el-table-column prop="totalamt" label="小计" sortable>
</el-table-column>
<el-table-column prop="maintain.optName" label="维修员" sortable>
</el-table-column>
<el-table-column label="操作" width="150">
<template scope="scope">
<el-button size="small" @click="itemhandleEdit(scope.$index, scope.row)">修改</el-button>
<el-button type="danger" size="small" @click="itemhandleDel(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--明细下方工具条-->
<el-col :span="24" class="itemtoolbar">
<el-button type="danger" @click="itembatchRemove" :disabled="this.itemsels.length===0">批量删除</el-button>
<!--分页显示-->
<el-pagination layout="total,prev, pager, next" @current-change="itemhandleCurrentChange" :page-size="5" :total="itemtotal" style="float:right;">
</el-pagination>
</el-col>
<!--明细编辑界面-->
<el-dialog title="明细编辑:" v-model="repairorderitemFormVisible" :close-on-click-modal="false">
<el-form :model="repairorderitem" label-width="80px" :rules="itemeditFormRules" ref="itemeditForm">
<!--维修员下拉框-->
<el-form-item label="维修员" prop="maintainId">
<el-select v-model="repairorderitem.maintain.id" >
<!--Ajax查找维修员信息:maintainlist-->
<el-option v-for="item in maintainlist" :key="item.id"
:label="item.optName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<!--配件下拉框-->
<el-form-item label="配件" prop="carComponent">
<el-select v-model="repairorderitem.carComponent.id" >
<!--Ajax查找配件信息:componentlist-->
<el-option v-for="item in componentlist" :key="item.id"
:label="item.partsName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="配件数量" prop="num" >
<el-input v-model="repairorderitem.num" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="工时费" prop="amt2">
<el-input v-model="repairorderitem.amt2" auto-complete="off" ></el-input>
</el-form-item>
<el-form-item label="配件单价" prop="amt1" style="background-color: orange;">
<el-input v-model="repairorderitem.amt1" auto-complete="off" readonly></el-input>
</el-form-item>
<el-form-item label="小计" prop="totalamt" style="background-color: orange;">
<el-input v-model="repairorderitem.totalamt" auto-complete="off" readonly></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button style="background-color: orange" type="primary" @click.native="calculate" >小计</el-button>
<el-button @click.native="repairorderitemFormVisible = false">取消</el-button>
<el-button type="primary" @click="itemeditSubmit" >提交</el-button>
</div>
</el-dialog>
<!--结算界面-->
<el-dialog title="订单结算" v-model="settedVisible" :close-on-click-modal="false">
<el-form :model="settedVal" label-width="80px" :rules="setted1FormRules" ref="setted1">
<!-- 隐藏域存放id,修改回显用 -->
<!-- 但是注意由于此form表单是双向绑定,点击编辑按钮触发this.department = row;
id就已经存放到Vue的department中了,修改name由于双向绑定会改变department中的name,
在提交的时候是提交的model中的数据,所以此时不需要专门创建隐藏域存放id。可见双向绑定模式
解决了之前修改回需要专门的隐藏域存放id这种low比做法
-->
<el-form-item label="客户姓名" prop="custormer" style="background-color: #50bfff;" >
<el-input v-model="settedVal.custormer" auto-complete="off" readonly></el-input>
</el-form-item>
<el-form-item label="应付金额" prop="reAmount" style="background-color: orange;" >
<el-input v-model="settedVal.reAmount" auto-complete="off" readonly></el-input>
</el-form-item>
<el-form-item label="实付金额" prop="payAmount" style="background-color: yellow;">
<el-input v-model="settedVal.payAmount" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="支付方式" prop="payType">
<el-select label="支付方式" v-model="settedVal.paytype.id" placeholder="请选择支付方式">
<el-option label="现金" value="1"></el-option>
<el-option label="银行卡" value="2"></el-option>
<el-option label="微信" value="3"></el-option>
<el-option label="支付宝" value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="还车方式" prop="carType">
<el-radio v-model="settedVal.returnType.id" label="1">还车上门</el-radio>
<el-radio v-model="settedVal.returnType.id" label="2">到店自取</el-radio>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="settedVisible = false">取消</el-button>
<el-button type="primary" @click="settedSave">提交</el-button>
</div>
</el-dialog>
</section>
</div>
</template>
<!--++++++++++++++++++++++++++++++++++++++++++++++++++3、数据处理++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<script>
import util from '../../common/js/util'
//import NProgress from 'nprogress'
import { getUserListPage, removeUser, batchRemoveUser, editUser, addUser } from '../../api/api';
export default {
data() {
return {
/*==================================================================3.0、结算数据==============================*/
//结算弹窗
settedVisible:false,
//双击后选中的一行维修单数据
CurrentRowRepairorder:{
repairOrderItems:[]
},
//结算单数据
settedVal:{
custormer:'',
reAmount:null,
payAmount:null,
paytype:{
id:"请选择"
},
returnType:{
id:null
}
},
//结算框验证规则
/*setted1FormRules: {
payAmount: [
{ required: true, message: '请输入实付金额', trigger: 'blur' }
],
payType: [
{ required: true, message: '请选择支付方式', trigger: 'blur' }
],
carType: [
{ required: true, message: '请选择还车方式', trigger: 'blur' }
]
},*/
/*==================================================================3.1、维修单栏数据==============================*/
//维修单高级查询过滤器
filters: {
carnum: ''
},
//地图弹窗
mapdialogVisible:false,
//地图关键字
keyword:'',
//维修单列表值,默认为空,全局常量
repairorders: [],
//维修单列表,总页数,初始为0
total: 0,
//维修单列表页码,初始第一页
page: 1,
listLoading: false,
//维修单多选时,列表选中行,默认为空
sels: [],
//维修单编辑界面,默认关闭
repairorderFormVisible: false,
//维修单加载圈,默认关闭
editLoading: false,
//编辑框验证规则
editFormRules: {
customer: [
{ required: true, message: '请输入客户姓名', trigger: 'blur' }
],
carnum: [
{ required: true, message: '请输入车牌号', trigger: 'blur' }
],
address: [
{ required: true, message: '请输入还车地址', trigger: 'blur' }
]
},
//维修单编辑界面初始数据
repairorder: {
id: 0,
customer: '',
address:'',
carnum:'',
status:1,
maintain:{
id:'请选择'
}
},
/*测试用维修员数组*/
maintainlist:[
{'id':1,'optName':"测试员1"},
{'id':2,'optName':"测试员2"},
{'id':3,'optName':"测试员3"}
],
/*测试用汽车配件数组*/
componentlist:[
{'id':1,'partsName':"测试件1",price:10},
{'id':2,'partsName':"测试件2",price:20},
{'id':3,'partsName':"测试件3",price:30}
],
/*====================================================================3.2、明细栏数据================================*/
//明细栏显示的车牌号,当前选中展示出来的维修单车牌号
rep_carnum:'请双击选择维修单!',
//明细右上角提示,明细所属的维修单号,当前选中展示出来的维修单号
rep_id:0,
//初始化明细列表,默认为空
repairorderitems: [],
//明细分页
itemtotal: 0,//初始时总共0条
itempage: 1,//初始时为第一页
//明细加载,默认不加载
itemlistLoading: false,
//明细多选时,选中行的值
itemsels: [],
//明细编辑界面,默认关闭
repairorderitemFormVisible: false,
//明细加载圈
itemeditLoading: false,
//明细编辑框验证规则
itemeditFormRules: {
amt2: [
{ required: true, message: '请输入工时费', trigger: 'blur' }
],
num: [
{ required: true, message: '请输入配件数量', trigger: 'blur' }
]
},
//明细编辑界面初始值
repairorderitem: {
id: 0,
rep_id:this.rep_id,
carComponent:{
id:'请选择',
price:0
},
amt1:0,
num:0,
amt2:0,
totalamt:0,
maintain:{
id:'请选择'
}
}
}
},
/*=============================================================4、方法=====================================*/
/*=============================================================4.1、维修单栏方法=====================================*/
methods: {
//4.1.1、百度地图,弹窗
selectAdrress:function(){
this.mapdialogVisible=true;
},
//4.1.2、百度地图赋值给编辑框地址栏,关闭弹窗
selectAdrressConfirm:function(){
//获取百度地图选择的地址,js原始方法
/* var baiduaddr = document.getElementById("searchInput").value;
console.debug(baiduaddr)*/
//将地图值赋予编辑框地址栏
this.repairorder.address=this.keyword;
//关闭地图
this.mapdialogVisible=false;
},
//4.1.4、维修单换页
handleCurrentChange(val) {
//获取变动后的页码
this.page = val;
//刷新维修单
this.getRepairorders();
},
//4.1.5、维修单高级查询
queryRepairorders(){
//将页码置为首页
this.page=1;
//刷新维修单
this.getRepairorders();
//清空明细栏
this.rep_carnum='请双击选择维修单!';
this.rep_id=0;
this.getRepairorderitems();
},
//4.1.6、Ajax 获取维修单列表
getRepairorders() {
//设定请求参数
let para = {
//页数,长度
page: this.page,
pageSize:5,
//高级查询字段,车牌号,默认为空
keywords: this.filters.carnum
};
//开启加载圈
this.listLoading = true;
//发送Ajax
this.$http.post('/repairorder/query',para).then((res) => {
//设置分页数据
console.debug(res)
this.total = res.data.total;
//维修单列表赋值
this.repairorders = res.data.rows;
//关闭加载圈
this.listLoading = false;
});
},
//4.1.7、删除维修单
handleDel: function (index, row) {
//确认是否删除
this.$confirm('确认删除该记录吗?', '提示', {
type: 'warning'
}).then(() => {
//开启加载圈
this.listLoading = true;
//发送Ajax请求
this.$http.delete("/repairorder/"+row.id).then((res) => {
//关闭加载圈
this.listLoading = false;
//判断是否删除成功,进行不同的提示
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
};
//刷新维修单
this.getRepairorders();
//清空明细栏
this.rep_carnum='请双击选择维修单!';
this.rep_id=0;
this.getRepairorderitems();
});
}).catch(() => {
});
},
//4.1.8、弹出维修单编辑界面
handleEdit: function (index, row) {
//弹窗
this.repairorderFormVisible = true;
//回显作用 拷贝row到新的{}对象,防止修改时,主菜单栏也改变
this.repairorder = Object.assign({}, row);
},
//4.1.9、弹出维修单新增界面
handleAdd: function () {
//弹窗
this.repairorderFormVisible = true;
//初始化值
this.repairorder = {
id: 0,
customer: '',
address:'',
carnum:'',
status:1,
maintain:{
id:'请选择'
}
};
},
//4.1.10、保存维修单
editSubmit: function () {
this.$refs.editForm.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
//显示加载圈
this.editLoading = true;
//NProgress.start();
//备份表单里面数据,备分一份给para变量
let para = Object.assign({}, this.repairorder);
let url ='/repairorder/edit';
//发送请求
this.$http.put(url,para).then((res) => {
//NProgress.done();
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
}
//重置表单信息为null
this.$refs['editForm'].resetFields();
//关闭窗口
this.repairorderFormVisible = false;
//刷新维修单
this.filters.carnum='';
this.page=1;
this.getRepairorders();
//清空明细栏
this.rep_carnum='请双击选择维修单!';
this.rep_id=0;
this.getRepairorderitems();
});
});
}
});
},
//4.1.11、维修单多选时,选中项变化时取值
selsChange: function (sels) {
console.debug(sels)
this.sels = sels;
},
//4.1.12、批量删除
batchRemove: function () {
//弹窗确认是否删除
this.$confirm('确认删除选中记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.listLoading = true;
let para =this.sels;
this.$http.patch("/repairorder/deletes",para).then((res) => {
this.listLoading = false;
//根据前台返回的 AjaxResult,判断是否成功
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
};
//刷新维修单
this.getRepairorders();
//清空明细栏
this.rep_carnum='请双击选择维修单!';
this.rep_id=0;
this.getRepairorderitems();
});
}).catch(() => {
});
},
//4.1.13、双击维修单一行显示明细
showItems(row){
console.debug(row);
//将选中行赋值给中间变量
this.CurrentRowRepairorder=row;
//根据维修单号rep_id查询明细
this.rep_id=row.id;
//显示选中的车牌号
this.rep_carnum=row.carnum;
//分页加载
this.getRepairorderitems();
},
/*=======================================================4.2、明细栏方法===========================================*/
//4.2.1、明细分页换页
itemhandleCurrentChange(val) {
//获取当前页
this.itempage=val;
//分页加载
this.getRepairorderitems();
},
//4.2.2、明细小计方法
calculate(){
//求 单价:amt1,小计:totalamt
// 遍历Ajax 请求到的配件数组,
for (var i=0; i<this.componentlist.length;i++) {
var comp = this.componentlist[i];
let cid = this.repairorderitem.carComponent.id;
//当选中的配件编号 与 其中一个配件id相同时,进行计算,并结束遍历。
if (comp.id===cid){
console.debug("============================")
//①将配件赋予给明细
this.repairorderitem.carComponent=comp;
//②将 配件价格赋予给 明细单价
this.repairorderitem.carComponent.price=comp.price;
this.repairorderitem.amt1=comp.price;
//③计算小计
var a = Number(this.repairorderitem.carComponent.price* this.repairorderitem.num);
var b = Number(this.repairorderitem.amt2);
this.repairorderitem.totalamt=(a+b);
return;
}
}
},
//4.2.3、Ajax获取所有明细
getRepairorderitems() {
var para = {
page: this.itempage,
pageSize:5,
rep_id:this.rep_id
};
this.itemlistLoading = true;
this.$http.post('/repairorderitem/query',para).then((res) => {
this.itemtotal = res.data.total;
this.repairorderitems = res.data.rows;
this.itemlistLoading = false;
});
},
//4.2.4、删除一条明细
itemhandleDel: function (index, row) {
this.$confirm('确认删除该记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.itemlistLoading = true;
this.$http.delete("/repairorderitem/"+row.id).then((res) => {
console.debug(res)
/*removeUser(para).then((res) => {*/
this.itemlistLoading = false;
//NProgress.done();
//判断是否删除成功,进行不同的提示
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
};
//将页面置为首页
this.itempage=1;
//发送Ajax请求,刷新明细展示列表
this.getRepairorderitems();
});
}).catch(() => {
});
},
//4.2.5、弹出明细编辑界面
itemhandleEdit: function (index, row) {
//回显
this.repairorderitemFormVisible = true;
//回显作用 拷贝row到新的{}对象,防止修改时,主菜单栏也改变
this.repairorderitem = Object.assign({}, row);
},
//4.2.6、弹出明细新增界面
itemhandleAdd: function () {
//判断是否选中维修单
if(this.rep_id===0){
this.$message({
message: "请双击选择维修单!",
type: 'error'
});
return;
}
//清空
this.repairorderitemFormVisible = true;
this.repairorderitem = {
id: 0,
rep_id:this.rep_id,
carComponent:{
id:'请选择',
price:0
},
amt1:0,
num:0,
amt2:0,
totalamt:0,
maintain:{
id:'请选择'
}
};
//调用计算方法,初始化时,计算小计
this.calculate();
},
//4.2.7、明细保存提交
itemeditSubmit: function () {
this.$refs.itemeditForm.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.calculate();
//显示加载圈
this.itemeditLoading = true;
//备份表单里面数据,备分一份给para变量
let itempara = Object.assign({}, this.repairorderitem);
let itemurl ='/repairorderitem/edit';
//发送请求
this.$http.put(itemurl,itempara).then((res) => {
//NProgress.done();
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
}
//重置表单信息为null
this.$refs['itemeditForm'].resetFields();
//关闭窗口
this.repairorderitemFormVisible = false;
//发送Ajax请求,刷新明细展示列表
this.getRepairorderitems();
});
});
}
});
},
//4.2.8、获取,明细多选时,选中行数据
itemselsChange: function (itemsels) {
this.itemsels = itemsels;
},
//4.2.9、批量删除明细
itembatchRemove: function () {
this.$confirm('确认删除选中记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.itemlistLoading = true;
var itempara = this.itemsels;
this.$http.patch("/repairorderitem/deletes",itempara).then((res) => {
this.listLoading = false;
//根据前台返回的 AjaxResult,判断是否成功
if(res.data.success){
this.$message({
message: res.data.message,
type: 'success'
});
}else {
this.$message({
message: res.data.message,
type: 'error'
});
};
//刷新明细展示列表
this.getRepairorderitems();
});
}).catch(() => {
});
},
/*========================================================5、结算方法========================================*/
//5.1、结算弹窗的方法
setted(){
//判断是否选中维修单
if(this.rep_id===0){
this.$message({
message: "请双击选择需要结算的维修单!",
type: 'error'
});
return;
}
//(1)计算出结算订单的总金额
let amountSum = 0;
console.debug(this.CurrentRowRepairorder.repairOrderItems);
for (var index = 0; index < this.CurrentRowRepairorder.repairOrderItems.length; index++) {
amountSum=Number(amountSum+this.CurrentRowRepairorder.repairOrderItems[index].totalamt);
}
this.settedVal.reAmount= amountSum.toFixed(3);
//计算出结算订单的应付金额
this.settedVal.payAmount= amountSum.toFixed(3);
//顾客姓名
this.settedVal.custormer= this.CurrentRowRepairorder.customer;
//维修单id
this.settedVal.mai_id= this.CurrentRowRepairorder.id;
//地址
this.settedVal.address= this.CurrentRowRepairorder.address;
//结算单弹窗
this.settedVisible=true
},
//5.2、结算保存的方法
settedSave(){
this.$refs.setted1.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
//拷贝后面对象的值到新的对象,防止后面的代码改动引起模型的变化
let para = Object.assign({}, this.settedVal);
console.debug(para)
//添加与修改走同一个路径,所以不需要判断
this.$http.put("/setted",para).then((res) => {
this.$message({
message: '结算成功!',
type: 'success'
});
//重置表单
this.$refs['setted1'].resetFields();
//关闭对话框
this.settedVisible = false;
//刷新数据
this.getDepartments();
//刷新维修单
this.filters.carnum='';
this.page=1;
this.getRepairorders();
//清空明细栏
this.rep_carnum='请双击选择维修单!';
this.rep_id=0;
this.getRepairorderitems();
});
});
}
});
}
},
/*========================================================6、钩子方法========================================*/
mounted(){
//(1)获取维修单
this.getRepairorders();
//(2)Ajax获取所有维修员,用于下拉框
this.$http.patch('/Maintain/loadAll').then((res) => {
this.maintainlist=res.data;
});
//(3)Ajax获取所有汽车配件,用于下拉框
this.$http.patch('/carComponent').then((res) => {
this.componentlist=res.data;
});
}
}
</script>
<!--====================================================7、百度地图样式=====================================-->
<style scoped>
/*百度地图输入框样式*/
.searchinput{
width: 300px;
box-sizing: border-box;
padding: 9px;
border: 1px solid #dddee1;
line-height: 20px;
font-size: 16px;
height: 38px;
color: #333;
position: relative;
border-radius: 4px;
}
/* 地图宽、高*/
.map {
width: 100%;
height: 300px;
}
</style>
八、未使用技术
1、saas:
理解1:SaaS(https://baike.baidu.com/item/SaaS)平台是运营saas软件的平台。SaaS提供商为企业搭建信息化所需要的所有网络基础设施及软件、硬件运作平台,并负责所有前期的实施、后期的维护等一系列服务
理解2:
SaaS,是Software-as-a-Service的缩写名称,意思为[软件即服务]
以前的软件 – 怎么让用户使用的
我们服务的 都需要在用户的网络的部署一套,用户在它的网络里面可以使用
好不好:
好处:安全 自己的服务里面
不好的地方:
维护麻烦
Saas平台:各个公司 或者 各个用户 可以在我们自己saas平台服务上使用,前提 你需要购买服务
而我们把购买服务的这些客户或者公司,我们把它叫成租户
多租户面临一些问题,设计系统
1.2 如果我们一个系统基于Saas设计的,我们应该怎么用?
(1)方式一 每个租户使用独立数据库
(2)方式二 共享数据库,使用独立表
(3)方式三 共享数据库,共享表,使用tenant_id 区分
通过权限来控制数据的展示
1.3 saas的权限设计
平台管理员:
在saas权限最高,什么都可以做,管理各个租户 设定套餐
租户管理员
在平台注册的租户
用户
租户下面的用户
这些数据都可以存入一个表里面 目的登陆上面就方便多了
在每个表里面都应该存放一个字段tenant_id
1.4 租户的注册
租户注册 --存入两个表 一个租户表t_tenant 一个是员工表t_employee
搭建 后台(mapper controller service --写了保存方法)
前台form表单 (表单里面就是租户的信息)
2、前后端分离下的shiro
2.1 搭建shiro环境(掌握)
(1)导入相应的依赖的jar包
(2)applicationContext-shiro.xml
(3)在web.xml引入配置文件
配置代理过滤器
2.2完成登陆(掌握)
前端和后台
前端:
(1)准备一个登陆页面 ,准备表单
(2)点击登陆的时候,进入后台LoginController
(3)得到登陆返回的ajaxResult结果
分别把返回用户信息 和 session信息存入 前端的session里面
(4)登陆进可以进入主页
后台:
(1) 在LoginController获取到主体(当前用户)
(2)判断主体是否登陆过
没有登陆过 -->去登陆认证 login(token)
(3)进入登陆认证Realm里面
从数据库拿到用户的数据 比如密码
交个shiro进行认证
(4)LoginController认证完之后
把用户信息 存入到 AjaxResult
把sessionid 存入 AjaxResult
2.3点击部门管理的使用(掌握token方式完成会话管理)
问题: /department 访问后台的数据,但是被shiro拦截下来,看在cookie里面是否存在jsessionid。如果有,让你访问,如果没有 拦截 —前后分离模式 是前台是没有传递jsessionid
解决:
前端
(1) 每次在发送axios请求的时候,我们从前端session 里面取出token 放入
到请求的头里面 header(X-TOKEN)
(2) 前端每次发送axios这个请求,就会把信息到到后台
后台:
(1)shiro会把axios情求拦截下来,拦截下来之后,获取header里面的x-token的这些
—重写CrmSessionManager 从header里面获取
(2) 每次发送请求 发送预检options请求,shiro对它进行放行处理
/department --》 options(请求头 带了x-token) /patch(controller)
--写过滤器来放行请求 MyAuthenticationFilter
3、全文检索:lucene
3.1全文检索的核心(理解)
创建索引 和 搜索索引
3.2 对全文检索的API认识(理解)
(1)目录(Directory)
//构建一个索引目录来存放索引 .. 下面的代码 就根据自己应用环境选择适应的Directory
//现在开发 选择SimpleFSDirectory 来个目录
FSDirectory directory = FSDirectory.open(Paths.get(path))
(2)文档(Document 和 Field)操作
Document --类似数据库表里面一行记录
Field --类似数据库一行记录里面的列
Document: --crud的方法
indexWriter.addDocument(document1);
indexWriter.deleteDocuments(条件);
indexWriter.updateDocument(条件, 文档);
(3)字段Field的操作
//一种方式
document3.add(new TextField("title","doc3", Field.Store.YES ));
//添加字段
Document document3 = new Document();
FieldType fieldType = new FieldType();
fieldType.setStored(true);//是否存储 简介 介绍 --没有存储 (从数据库查询)
fieldType.setIndexOptions(IndexOptions.DOCS);//表示放入索引区 创建索引
fieldType.setTokenized(true);//表示要分词
//什么情况下要分词 一句话话 我是中国人 什么情况要不分词( 人名 地方 上海 省份证号 )
document3.add(new Field("title","doc3",fieldType))
3.3 分词(练习掌握)
luence怎么去分词
(1)手动打了jar包到本地仓库里面去
(2)在模块 引入ik分词器 – 引入lucene其他的包
(3)测试分词器
配置扩展的词和停用词
3.4 什么时候把数据同步到索引库
(1)即时同步,在crud的时候,同步到索引库
(2) 自动同步 – 借助定时器
(3) 手动同步 --页面添加按钮进行同步
3.5 项目引入LuceneUtil工具类
完成文档的增删改查
4、第三方认证:微信
客户端必须得到用户的授权,才能获得令牌,OAuth2.0定义了四种授权方式:
授权码模式(authorization code)
简化模式(implicit)
密码模式(resource owner password credentials)
客户端模式(client credentials)
这里,我们主要介绍一下授权码模式:
授权码模式是功能最完整,流程最严密的授权模式。它的特点是通过客户端的后台服务器,与“服务提供商”的认证服务器进行互动: