1 概念
00.分层
vo
dto
entity
enum
constant
common
result
task
filter
utils
config
exception
properties
controller
service
mapper
test
01.权限管理
用户管理
角色管理
菜单管理
部门管理
岗位管理
02.商品管理
SPU管理
SKU管理
发布商品
商品规格管理
商品类别管理
商品信息管理
电商三核:商品、订单、库存
java三高:高并发、高可用、高性能
03.项目区别
OA 办公自动化:员工管理、请假报销、业务审批
ERP 协调企业资源:员工、生产、制造、采购、分销、质量
CRM 客户管理系统:利润分析、性能分析、未来分析、产品分析
CMS 电商CMS内容管理系统:运营上传网站促销活动发布上线,全程不需要技术部门参与
关键字 GVP、电商项目、支付项目 | 仓库、超市、订单、购物、货运、采购、进销存(wms)
2 VUE引入
2.1 JS写法.js
// 引用完整版 Vue,方便讲解
import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
id += 1;
return { id: id, name: name, gender: gender };
};
new Vue({
// 01.html模板
template: `
<div>
<div>
<button @click="setGender('') ">全部</button>
<button @click="setGender('male')">男</button>
<button @click="setGender('female')">女</button></div>
<ul>
<li v-for="(u,index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
</ul>
</div>
`,
// 02.响应data中property
data() {
return {
users: [
createUser("方方", "男"),
createUser("圆圆", "女"),
createUser("小新", "男"),
createUser("小葵", "女")
],
gender: ""
};
},
// 02.响应data中property
computed: {
displayUsers() {
const hash = {
male: "男",
female: "女"
};
const { users, gender } = this;
if (gender === "") {
return users;
} else if (typeof gender === "string") {
return users.filter(u => u.gender === hash[gender]);
} else {
throw new Error("gender 的值是意外的值");
}
}
},
methods: {
setGender(string) {
this.gender = string;
}
},
}).$mount("#app");
2.2 单文件写法.vue
<template lang="jade">
div
p {{ greeting }} World!
Component1
</template>
<script>
// 导入组件中方法
import { listOrder, getOrder, delOrder, addOrder, updateOrder } from '@/api/microsoft/order'
// 导入组件
import Component1 from './Component1.vue'
export default {
// 禁用默认继承
inheritAttrs:false,
name: 'Order',
components: { Component1, Component2},
props: {},
data () {
return {
greeting: 'Hello'
}
},
watch: {},
computed: {},
created() {},
mounted() {},
methods: {
method1(){},
method2(){},
method3(){},
},
}
</script>
<style lang="stylus" scoped>
p {
font-size 2em;
text-align center;
}
</style>
3 税率、税额、数量
3.1 前端
税率、税额、数量
数量 10
单价-税前 25
税率 0.13
税额 10*25*0.13
单价-税后 25*(1+0.13)
总价-税前 25* 10
总价-税后 25*(1+0.13)*10
<!-- 修改订单对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="数量" prop="num">
<el-input v-model.number="form.num" placeholder="请输入数量" clearable/>
</el-form-item>
<el-form-item label="单价-税前" prop="unitPriceTaxBefore">
<el-input v-model.trim="form.unitPriceTaxBefore" placeholder="请输入单价-税前" :disabled="true"/>
</el-form-item>
<el-form-item label="税率" prop="rate">
<el-input v-model.trim="form.rate" placeholder="请输入税率" :disabled="true"/>
</el-form-item>
<el-form-item label="税额">
<el-input v-model.trim="tax1" :disabled="true"/>
</el-form-item>
<el-form-item label="单价-税后">
<el-input v-model.trim="unitPriceTaxAfter1" :disabled="true"/>
</el-form-item>
<el-form-item label="总价-税前">
<el-input v-model.trim="sumPriceTaxBefore1" :disabled="true"/>
</el-form-item>
<el-form-item label="总价-税后">
<el-input v-model.trim="sumPriceTaxAfter1" :disabled="true"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 添加订单对话框 -->
<el-dialog :title="title2" :visible.sync="open2" width="500px" append-to-body>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="100px">
<el-form-item label="数量" prop="num">
<el-input v-model.number="form2.num" placeholder="请输入数量" clearable/>
</el-form-item>
<el-form-item label="单价-税前" prop="unitPriceTaxBefore">
<el-input v-model.trim="form2.unitPriceTaxBefore" placeholder="请输入单价-税前" :disabled="true"/>
</el-form-item>
<el-form-item label="税率" prop="rate">
<el-input v-model.trim="form2.rate" placeholder="请输入税率" :disabled="true"/>
</el-form-item>
<el-form-item label="税额">
<el-input v-model.trim="tax2" :disabled="true"/>
</el-form-item>
<el-form-item label="单价-税后">
<el-input v-model.trim="unitPriceTaxAfter2" :disabled="true"/>
</el-form-item>
<el-form-item label="总价-税前">
<el-input v-model.trim="sumPriceTaxBefore2" :disabled="true"/>
</el-form-item>
<el-form-item label="总价-税后">
<el-input v-model.trim="sumPriceTaxAfter2" :disabled="true"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm2">确 定</el-button>
<el-button @click="cancel2">取 消</el-button>
</div>
</el-dialog>
-------------------------------------------------------------------------------------------------------------
export default {
name: 'Order',
components: { importTable },
dicts: ['sys_order_status', 'sys_fulfillment_type'],
data() {
return {
/** 表格列表:编辑 */
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 表单参数
form: {
poNumber: null,
cusName: null,
sku: null,
productName: null,
products: null,
resellerId: null,
orderStatus: null,
orderDate: null,
num: '',
unitPriceTaxBefore: '',
rate: '',
tax: '',
unitPriceTaxAfter: '',
sumPriceTaxBefore: '',
sumPriceTaxAfter: ''
},
// 表单校验
rules: {
poNumber: [
{ required: true, message: 'PO单号不能为空', trigger: 'blur' }
],
cusName: [
{ required: true, message: '客户名称不能为空', trigger: 'blur' }
],
productName: [
// { required: true, message: '产品名称不能为空', trigger: 'blur' }
],
sku: [
{ required: true, message: '产品型号不能为空', trigger: 'blur' }
],
num: [
{ type: 'number', required: true, message: '数量必须为整数,如1、2', trigger: 'blur' }
],
},
/** 表格列表:新增 */
// 弹出层标题
title2: '',
// 是否显示弹出层
open2: false,
// 表单参数
form2: {
poNumber: null,
cusName: null,
sku: null,
productName: null,
products: null,
resellerId: null,
orderStatus: null,
orderDate: null,
num: '',
unitPriceTaxBefore: '',
rate: '',
tax: '',
unitPriceTaxAfter: '',
sumPriceTaxBefore: '',
sumPriceTaxAfter: ''
},
// 表单校验
rules2: {
poNumber: [
{ required: true, message: 'PO单号不能为空', trigger: 'blur' }
],
cusName: [
{ required: true, message: '客户名称不能为空', trigger: 'blur' }
],
productName: [
// { required: true, message: '产品名称不能为空', trigger: 'blur' }
],
sku: [
{ required: true, message: '产品型号不能为空', trigger: 'blur' }
],
num: [
{ type: 'number', required: true, message: '数量必须为整数,如1、2', trigger: 'blur' }
],
// unitPriceTaxBefore: [
// { required: true, message: '单价-税前必须为数字,如0.12、0.1234、10、10.00、10.12', trigger: 'blur' },
// {
// transform(value) {
// return Number(value);
// },
// validator(rule, value, callback) {
// if (Number.isFinite(value) && value > 0) {
// callback();
// } else {
// callback(new Error("请输入不小于0的数字"));
// }
// },
// trigger: "blur",
// }
// ]
},
},
computed: {
tax1: function() {
return (this.form.num * this.form.unitPriceTaxBefore * this.form.rate).toFixed(4)
},
unitPriceTaxAfter1: function() {
return (this.form.unitPriceTaxBefore * (1 + 0.13)).toFixed(4)
},
sumPriceTaxBefore1: function() {
return (this.form.num * this.form.unitPriceTaxBefore).toFixed(4)
},
sumPriceTaxAfter1: function() {
return (this.form.unitPriceTaxBefore * (1 + 0.13) * this.form.num).toFixed(4)
},
tax2: function() {
return (this.form2.num * this.form2.unitPriceTaxBefore * this.form2.rate).toFixed(4)
},
unitPriceTaxAfter2: function() {
return (this.form2.unitPriceTaxBefore * (1 + 0.13)).toFixed(4)
},
sumPriceTaxBefore2: function() {
return (this.form2.num * this.form2.unitPriceTaxBefore).toFixed(4)
},
sumPriceTaxAfter2: function() {
return (this.form2.unitPriceTaxBefore * (1 + 0.13) * this.form2.num).toFixed(4)
}
},
methods: {
submitForm() {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.id != null) {
this.form.tax = (this.form.num * this.form.unitPriceTaxBefore * this.form.rate).toFixed(4)
this.form.unitPriceTaxAfter = (this.form.unitPriceTaxBefore * (1 + 0.13)).toFixed(4)
this.form.sumPriceTaxBefore = (this.form.num * this.form.unitPriceTaxBefore).toFixed(4)
this.form.sumPriceTaxAfter = (this.form.unitPriceTaxBefore * (1 + 0.13) * this.form.num).toFixed(4)
this.$modal.confirm('是否保存?').then(() => {
this.loading = true
updateOrder(this.form).then(res => {
this.loading = false
this.$modal.msgSuccess(res.msg)
this.open = false
this.getList()
},
err => {
this.loading = false
// this.$modal.msgError(err.msg)
})
})
}
}
})
},
submitForm2() {
this.$refs['form2'].validate(valid => {
if (valid) {
this.form2.tax = (this.form2.num * this.form2.unitPriceTaxBefore * this.form2.rate).toFixed(4)
this.form2.unitPriceTaxAfter = (this.form2.unitPriceTaxBefore * (1 + 0.13)).toFixed(4)
this.form2.sumPriceTaxBefore = (this.form2.num * this.form2.unitPriceTaxBefore).toFixed(4)
this.form2.sumPriceTaxAfter = (this.form2.unitPriceTaxBefore * (1 + 0.13) * this.form2.num).toFixed(4)
this.$modal.confirm('是否保存?').then(() => {
this.loading = true
addOrder(this.form2).then(res => {
this.loading = false
this.$modal.msgSuccess(res.msg)
this.open2 = false
this.getList()
},
err => {
this.loading = false
// this.$modal.msgError(err.msg)
})
})
}
})
},
}
}
-------------------------------------------------------------------------------------------------------------
// 新增订单
export function addOrder(data) {
return request({
url: '/microsoft/order/add',
method: 'post',
data: data
})
}
// 修改订单
export function updateOrder(data) {
return request({
url: '/microsoft/order/update',
method: 'put',
data: data
})
}
3.2 后端
@Api("订单接口")
@RestController
@RequestMapping("/microsoft/order")
public class PurchaseOrderController extends BaseController {
/**
* 新增订单
*/
@PreAuthorize("@ss.hasPermi('microsoft:order:add')")
@Log(title = "订单", businessType = BusinessType.INSERT)
@PostMapping(value = "/add")
public AjaxResult orderAdd(@RequestBody PurchaseOrder purchaseOrder) {
String operName = getUsername();
return toAjax(purchaseOrderService.orderAdd(purchaseOrder, operName));
}
/**
* 修改订单
*/
@PreAuthorize("@ss.hasPermi('microsoft:order:edit')")
@Log(title = "订单", businessType = BusinessType.UPDATE)
@PutMapping(value = "/update")
public AjaxResult orderEdit(@RequestBody PurchaseOrder purchaseOrder) {
String operName = getUsername();
return toAjax(purchaseOrderService.orderEdit(purchaseOrder, operName));
}
}
-------------------------------------------------------------------------------------------------------------
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
private static final Logger log = LoggerFactory.getLogger(PurchaseOrderServiceImpl.class);
/**
* 新增订单
*
* @param purchaseOrder 订单
* @return 结果
*/
@Override
public int orderAdd(PurchaseOrder purchaseOrder, String operName) {
// 获取当前客户名称数据
String orderCusName = purchaseOrder.getCusName();
purchaseOrder.setResellerId(orderCusName);
CusName selectCusName = cusNameMapper.selectCusName(orderCusName);
// 1.向 ms_cus_name 插入数据 (若不存在)
CusName cusName = new CusName();
if (selectCusName == null) {
cusName.setCusName(orderCusName);
cusName.setCreateTime(new Date());
cusName.setCreatePer(operName);
cusNameMapper.insertCusName(cusName);
}
// 2.向 ms_purchase_order 插入数据
purchaseOrder.setOrderStatus(1L);
Date date = new Date();
purchaseOrder.setCreateTime(date);
purchaseOrder.setUpdateTime(date);
purchaseOrder.setCreateMan(operName);
purchaseOrder.setUpdateMan(operName);
purchaseOrder.setOrderDate(date);
return purchaseOrderMapper.insertPurchaseOrder(purchaseOrder);
}
/**
* 修改订单
*
* @param purchaseOrder 订单
* @return 结果
*/
@Override
public int orderEdit(PurchaseOrder purchaseOrder, String operName) {
// 获取当前客户名称数据
String orderCusName = purchaseOrder.getCusName();
purchaseOrder.setResellerId(orderCusName);
CusName selectCusName = cusNameMapper.selectCusName(orderCusName);
// 1.向 ms_cus_name 插入数据 (若不存在)
CusName cusName = new CusName();
if (selectCusName == null) {
cusName.setCusName(orderCusName);
cusName.setCreateTime(new Date());
cusName.setCreatePer(purchaseOrder.getCreateBy());
cusNameMapper.insertCusName(cusName);
}
// 2.向 ms_purchase_order 更新数据
Date date = new Date();
purchaseOrder.setUpdateMan(operName);
purchaseOrder.setUpdateTime(date);
purchaseOrder.setOrderDate(date);
return purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
}
}
-------------------------------------------------------------------------------------------------------------
public interface CusNameMapper {
int insertCusName(CusName cusName);
}
<mapper namespace="com.ekostar.microsoft.mapper.CusNameMapper">
<insert id="insertCusName" parameterType="CusName" useGeneratedKeys="true" keyProperty="id">
insert into ms_cus_name
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="cusName != null">cus_name,</if>
<if test="createPer != null">create_per,</if>
<if test="createTime != null">create_time,</if>
<if test="isDeleted != null">is_deleted,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="cusName != null">#{cusName},</if>
<if test="createPer != null">#{createPer},</if>
<if test="createTime != null">#{createTime},</if>
<if test="isDeleted != null">#{isDeleted},</if>
</trim>
</insert>
</mapper>
-------------------------------------------------------------------------------------------------------------
public interface PurchaseOrderMapper {
/**
* 新增订单
*
* @param purchaseOrder 订单
* @return 结果
*/
int insertPurchaseOrder(PurchaseOrder purchaseOrder);
/**
* 修改订单
*
* @param purchaseOrder 订单
* @return 结果
*/
int updatePurchaseOrder(PurchaseOrder purchaseOrder);
}
<mapper namespace="com.ekostar.microsoft.mapper.PurchaseOrderMapper">
<insert id="insertPurchaseOrder" parameterType="PurchaseOrder" useGeneratedKeys="true" keyProperty="id">
insert into ms_purchase_order
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="poNumber != null">po_number,</if>
<if test="productName != null">product_name,</if>
<if test="sku != null">sku,</if>
<if test="products != null">products,</if>
<if test="resellerId != null">reseller_id,</if>
<if test="orderStatus != null">order_status,</if>
<if test="orderDate != null">order_date,</if>
<if test="num != null">num,</if>
<if test="tax != null">tax,</if>
<if test="rate != null">rate,</if>
<if test="unitPriceTaxBefore != null">unit_price_tax_before,</if>
<if test="unitPriceTaxAfter != null">unit_price_tax_after,</if>
<if test="sumPriceTaxBefore != null">sum_price_tax_before,</if>
<if test="sumPriceTaxAfter != null">sum_price_tax_after,</if>
<if test="isoCountryCode != null">iso_country_code,</if>
<if test="clientTransactionId != null">client_transaction_id,</if>
<if test="storeId != null">store_id,</if>
<if test="fulfillmentType != null">fulfillment_type,</if>
<if test="tokenPackage != null">token_package,</if>
<if test="isDeleted != null">is_deleted,</if>
<if test="cusName != null">cus_name,</if>
<if test="createTime != null">create_time,</if>
<if test="createMan != null">create_man,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateMan != null">update_man,</if>
<if test="orderTime != null">order_time,</if>
<if test="orderMan != null">order_man,</if>
<if test="delTime != null">del_time,</if>
<if test="delMan != null">del_man,</if>
<if test="returnTime != null">return_time,</if>
<if test="returnMan != null">return_man,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="poNumber != null">#{poNumber},</if>
<if test="productName != null">#{productName},</if>
<if test="sku != null">#{sku},</if>
<if test="products != null">#{products},</if>
<if test="resellerId != null">#{resellerId},</if>
<if test="orderStatus != null">#{orderStatus},</if>
<if test="orderDate != null">#{orderDate},</if>
<if test="num != null">#{num},</if>
<if test="tax != null">#{tax},</if>
<if test="rate != null">#{rate},</if>
<if test="unitPriceTaxBefore != null">#{unitPriceTaxBefore},</if>
<if test="unitPriceTaxAfter != null">#{unitPriceTaxAfter},</if>
<if test="sumPriceTaxBefore != null">#{sumPriceTaxBefore},</if>
<if test="sumPriceTaxAfter != null">#{sumPriceTaxAfter},</if>
<if test="isoCountryCode != null">#{isoCountryCode},</if>
<if test="clientTransactionId != null">#{clientTransactionId},</if>
<if test="storeId != null">#{storeId},</if>
<if test="fulfillmentType != null">#{fulfillmentType},</if>
<if test="tokenPackage != null">#{tokenPackage},</if>
<if test="isDeleted != null">#{isDeleted},</if>
<if test="cusName != null">#{cusName},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createMan != null">#{createMan},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateMan != null">#{updateMan},</if>
<if test="orderTime != null">#{orderTime},</if>
<if test="orderMan != null">#{orderMan},</if>
<if test="delTime != null">#{delTime},</if>
<if test="delMan != null">#{delMan},</if>
<if test="returnTime != null">#{returnTime},</if>
<if test="returnMan != null">#{returnMan},</if>
</trim>
</insert>
<update id="updatePurchaseOrder" parameterType="PurchaseOrder">
update ms_purchase_order
<trim prefix="SET" suffixOverrides=",">
<if test="poNumber != null">po_number = #{poNumber},</if>
<if test="productName != null">product_name = #{productName},</if>
<if test="sku != null">sku = #{sku},</if>
<if test="products != null">products = #{products},</if>
<if test="resellerId != null">reseller_id = #{resellerId},</if>
<if test="orderStatus != null">order_status = #{orderStatus},</if>
<if test="orderDate != null">order_date = #{orderDate},</if>
<if test="num != null">num = #{num},</if>
<if test="tax != null">tax = #{tax},</if>
<if test="rate != null">rate = #{rate},</if>
<if test="unitPriceTaxBefore != null">unit_price_tax_before = #{unitPriceTaxBefore},</if>
<if test="unitPriceTaxAfter != null">unit_price_tax_after = #{unitPriceTaxAfter},</if>
<if test="sumPriceTaxBefore != null">sum_price_tax_before = #{sumPriceTaxBefore},</if>
<if test="sumPriceTaxAfter != null">sum_price_tax_after = #{sumPriceTaxAfter},</if>
<if test="isoCountryCode != null">iso_country_code = #{isoCountryCode},</if>
<if test="clientTransactionId != null">client_transaction_id = #{clientTransactionId},</if>
<if test="storeId != null">store_id = #{storeId},</if>
<if test="fulfillmentType != null">fulfillment_type = #{fulfillmentType},</if>
<if test="tokenPackage != null">token_package = #{tokenPackage},</if>
<if test="isDeleted != null">is_deleted = #{isDeleted},</if>
<if test="cusName != null">cus_name = #{cusName},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="createMan != null">create_man = #{createMan},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateMan != null">update_man = #{updateMan},</if>
<if test="orderTime != null">order_time = #{orderTime},</if>
<if test="orderMan != null">order_man = #{orderMan},</if>
<if test="delTime != null">del_time = #{delTime},</if>
<if test="delMan != null">del_man = #{delMan},</if>
<if test="returnTime != null">return_time = #{returnTime},</if>
<if test="returnMan != null">return_man = #{returnMan},</if>
<if test="purchaseFailedNum != null">purchase_failed_num = #{purchaseFailedNum},</if>
</trim>
where id = #{id}
</update>
</mapper>
4 下拉框
4.1 前端1
options: [{
sku: 'KLQ-00638',
productName: 'M365 Bus Standard Retail ChnSimp Subscr 1YR China Only Medialess P8'
}, {
sku: 'T5D-03499',
productName: 'Office Home and Business 2021 ChnSimp China Only Medialess'
}],
-------------------------------------------------------------------------------------------------------------
<template>
<div>
<select v-model="selectedOption" @change="changeHandler">
<option v-for="option in options" :key="option.value" :value="option.value">
{{ option.label }}
</option>
</select>
<select v-model="selectedSubOption">
<option v-for="subOption in subOptions" :key="subOption.value" :value="subOption.value">
{{ subOption.label }}
</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
selectedOption: '',
options: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
],
selectedSubOption: '',
subOptions: [
{ value: 'suboption1', label: 'Suboption 1' },
{ value: 'suboption2', label: 'Suboption 2' }
]
}
},
methods: {
changeHandler() {
if (this.selectedOption === 'option1') {
this.selectedSubOption = 'suboption1'
} else {
this.selectedSubOption = 'suboption2'
}
}
}
}
</script>
4.2 前端2
options: [{
sku: 'KLQ-00638',
productName: 'M365 Bus Standard Retail ChnSimp Subscr 1YR China Only Medialess P8'
}, {
sku: 'T5D-03499',
productName: 'Office Home and Business 2021 ChnSimp China Only Medialess'
}],
-------------------------------------------------------------------------------------------------------------
<template>
<div>
<select v-model="selectedOption" @change="changeHandler">
<option v-for="option in options" :key="option.value" :value="option.value">
{{ option.label }}
</option>
</select>
<select v-model="selectedSubOption">
<option v-for="subOption in subOptions" :key="subOption.value" :value="subOption.value">
{{ subOption.label }}
</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
selectedOption: '',
options: [
{ value: 'option1', label: 'Option 1', subValue: 'suboption1' },
{ value: 'option2', label: 'Option 2', subValue: 'suboption2' }
],
selectedSubOption: '',
subOptions: [
{ value: 'suboption1', label: 'Suboption 1' },
{ value: 'suboption2', label: 'Suboption 2' }
]
}
},
methods: {
changeHandler() {
let selectedOption = this.options.find(option => option.value === this.selectedOption)
this.selectedSubOption = selectedOption.subValue
}
}
}
</script>
4.3 前端3
<!-- 修改订单对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="产品型号" prop="sku">
<el-select v-model="form.sku" clearable placeholder="请输入产品型号" class="inline-input" @change="changeHandler">
<el-option
v-for="item in options"
:key="item.sku"
:label="item.sku"
:value="item.sku"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-select v-model="form.productName" clearable placeholder="请输入产品名称" class="inline-input" disabled>
<el-option
v-for="item in options"
:key="item.productName"
:label="item.productName"
:value="item.productName"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="单价-税前" prop="unitPriceTaxBefore">
<el-select v-model="form.unitPriceTaxBefore" clearable placeholder="请输入单价-税前" class="inline-input" disabled>
<el-option
v-for="item in options"
:key="item.unitPriceTaxBefore"
:label="item.unitPriceTaxBefore"
:value="item.unitPriceTaxBefore"
>
</el-option>
</el-select>
</el-form-item>
<el-form/>
<el-dialog/>
<!-- 添加订单对话框 -->
<el-dialog :title="title2" :visible.sync="open2" width="500px" append-to-body>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="100px">
<el-form-item label="产品型号" prop="sku">
<el-select v-model="form2.sku" clearable placeholder="请输入产品型号" class="inline-input" @change="changeHandler2">
<el-option
v-for="item in options2"
:key="item.sku"
:label="item.sku"
:value="item.sku"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-select v-model="form2.productName" clearable placeholder="请输入产品名称" class="inline-input" disabled>
<el-option
v-for="item in options2"
:key="item.productName"
:label="item.productName"
:value="item.productName"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="单价-税前" prop="unitPriceTaxBefore">
<el-select v-model="form2.unitPriceTaxBefore" clearable placeholder="请输入单价-税前" class="inline-input" disabled>
<el-option
v-for="item in options2"
:key="item.unitPriceTaxBefore"
:label="item.unitPriceTaxBefore"
:value="item.unitPriceTaxBefore"
>
</el-option>
</el-select>
</el-form-item>
<el-form/>
<el-dialog/>
-------------------------------------------------------------------------------------------------------------
export default {
name: 'Order',
components: { importTable },
dicts: ['sys_order_status', 'sys_fulfillment_type'],
data() {
return {
/** 下拉框:产品型号、产品名称 */
// options: [{
// sku: 'KLQ-00638',
// productName: 'M365 Bus Standard Retail ChnSimp Subscr 1YR China Only Medialess P8'
// }, {
// sku: 'T5D-03499',
// productName: 'Office Home and Business 2021 ChnSimp China Only Medialess'
// }],
options: [],
options2: []
}
},
created() {
this.getList()
},
methods: {
getList() {
this.getCusCollect()
}
/** 下拉框:产品型号、产品名称 */
changeHandler() {
// if (this.form2.sku == 'KLQ-00638') {
// this.form2.productName = 'M365 Bus Standard Retail ChnSimp Subscr 1YR China Only Medialess P8 -----------'
// } else if (this.form2.sku == 'T5D-03499') {
// this.form2.productName = 'Office Home and Business 2021 ChnSimp China Only Medialess ---------'
// } else {
// this.form2.productName = ''
// }
let selectedOption = this.options.find(option => option.sku === this.form.sku)
this.form.productName = selectedOption.productName
this.form.unitPriceTaxBefore = selectedOption.unitPriceTaxBefore
},
changeHandler2() {
let selectedOption = this.options.find(option => option.sku === this.form2.sku)
this.form2.productName = selectedOption.productName
this.form2.unitPriceTaxBefore = selectedOption.unitPriceTaxBefore
},
/** 客户列表 */
getCusCollect() {
doCusCollect().then(response => {
// JS手动将数组中的对象添加一个value属性
this.restaurants = response.data.cusNameList.map(item => {
return {
...item,
value: item.cusName
}
})
this.options = response.data.productRefList
this.options2 = response.data.productRefList
})
}
}
}
-------------------------------------------------------------------------------------------------------------
export function doCusCollect(query) {
return request({
url: '/microsoft/order/baseInfoList',
method: 'get',
params: query
})
}
4.4 后端
@Data
public class BaseInfoResponse {
//客户名称列表
public List<CusName> cusNameList;
//产品对象列表
public List<ProductRef> productRefList;
}
-------------------------------------------------------------------------------------------------------------
@Api("订单接口")
@RestController
@RequestMapping("/microsoft/order")
public class PurchaseOrderController extends BaseController {
@Autowired
private IPurchaseOrderService purchaseOrderService;
/**
* 下拉列表
* @return
*/
@PreAuthorize("@ss.hasPermi('microsoft:order:baseInfoList')")
@GetMapping("/baseInfoList")
public AjaxResult orderCusCollect() {
BaseInfoResponse baseInfoResponse = purchaseOrderService.orderCusCollect();
return AjaxResult.success(baseInfoResponse);
}
}
-------------------------------------------------------------------------------------------------------------
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
private static final Logger log = LoggerFactory.getLogger(PurchaseOrderServiceImpl.class);
@Autowired
private CusNameMapper cusNameMapper;
@Autowired
private ProductRefMapper productRefMapper;
@Override
public BaseInfoResponse orderCusCollect() {
BaseInfoResponse baseInfoResponse = new BaseInfoResponse();
List<CusName> cusNames = cusNameMapper.selectCusList();
if (!CollectionUtils.isEmpty(cusNames)) {
baseInfoResponse.setCusNameList(cusNames);
}
List<ProductRef> productRefs = productRefMapper.selectProductRefs();
if (!CollectionUtils.isEmpty(productRefs)) {
baseInfoResponse.setProductRefList(productRefs);
}
return baseInfoResponse;
}
}
-------------------------------------------------------------------------------------------------------------
public interface CusNameMapper {
List<CusName> selectCusList();
}
<mapper namespace="com.ekostar.microsoft.mapper.CusNameMapper">
<resultMap type="CusName" id="CusNameResult">
<result property="id" column="id" />
<result property="cusName" column="cus_name" />
<result property="createPer" column="create_per" />
<result property="createTime" column="create_time" />
<result property="isDeleted" column="is_deleted" />
</resultMap>
<select id="selectCusList" resultType="com.ekostar.microsoft.domain.CusName" resultMap="CusNameResult">
select id, cus_name, create_per, create_time
from ms_cus_name
where is_deleted = 1
</select>
</mapper>
CREATE TABLE `ms_cus_name` (
`id` bigint NOT NULL AUTO_INCREMENT,
`cus_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '客户名称',
`create_per` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`is_deleted` tinyint DEFAULT '1' COMMENT '逻辑删除状态;1-未删除;2-删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='客户名称表';
-------------------------------------------------------------------------------------------------------------
public interface ProductRefMapper {
List<ProductRef> selectProductRefs();
}
<mapper namespace="com.ekostar.microsoft.mapper.ProductRefMapper">
<resultMap type="ProductRef" id="ProductRefResult">
<result property="id" column="id" />
<result property="productName" column="product_name" />
<result property="sku" column="sku" />
<result property="isDeleted" column="is_deleted" />
<result property="returnable" column="returnable" />
<result property="unitPriceTaxBefore" column="unit_price_tax_before" />
</resultMap>
<select id="selectProductRefs" resultType="com.ekostar.microsoft.domain.ProductRef" resultMap="ProductRefResult">
select id, product_name, sku, returnable, unit_price_tax_before
from ms_product_ref
where is_deleted = 1
</select>
</mapper>
CREATE TABLE `ms_product_ref` (
`id` bigint NOT NULL AUTO_INCREMENT,
`product_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '产品名称',
`sku` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '产品型号',
`is_deleted` tinyint DEFAULT '1' COMMENT '逻辑删除状态:1-未删除;2-删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='产品对象表';
5 客户列表
5.1 前端
<!-- 修改订单对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="客户名称" prop="cusName">
<el-autocomplete
class="inline-input"
v-model.trim="form.cusName"
:fetch-suggestions="querySearch"
placeholder="请输入客户名称"
clearable
></el-autocomplete>
</el-form-item>
</el-form>
<el-dialog/>
<!-- 添加订单对话框 -->
<el-dialog :title="title2" :visible.sync="open2" width="500px" append-to-body>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="100px">
<el-form-item label="客户名称" prop="cusName" :required="true">
<el-autocomplete
class="inline-input"
v-model.trim="form2.cusName"
:fetch-suggestions="querySearch"
placeholder="请输入客户名称"
clearable
></el-autocomplete>
</el-form-item>
</el-form>
<el-dialog/>
-------------------------------------------------------------------------------------------------------------
export default {
name: 'Order',
components: { importTable },
dicts: ['sys_order_status', 'sys_fulfillment_type'],
data() {
return {
/** input模板:自定义模板 */
restaurants: [],
}
},
created() {
this.getList()
},
methods: {
getList() {
this.getCusCollect()
}
/** input模板:自定义模板 */
querySearch(queryString, cb) {
var restaurants = this.restaurants
var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
// 调用 callback 返回建议列表的数据
cb(results)
},
createFilter(queryString) {
return (restaurant) => {
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
}
},
/** 客户列表 */
getCusCollect() {
doCusCollect().then(response => {
// JS手动将数组中的对象添加一个value属性
this.restaurants = response.data.cusNameList.map(item => {
return {
...item,
value: item.cusName
}
this.options = response.data.productRefList
this.options2 = response.data.productRefList
})
})
}
}
}
-------------------------------------------------------------------------------------------------------------
export function doCusCollect(query) {
return request({
url: '/microsoft/order/baseInfoList',
method: 'get',
params: query
})
}
5.2 后端
@Data
public class BaseInfoResponse {
//客户名称列表
public List<CusName> cusNameList;
//产品对象列表
public List<ProductRef> productRefList;
}
-------------------------------------------------------------------------------------------------------------
@Api("订单接口")
@RestController
@RequestMapping("/microsoft/order")
public class PurchaseOrderController extends BaseController {
@Autowired
private IPurchaseOrderService purchaseOrderService;
/**
* 下拉列表
* @return
*/
@PreAuthorize("@ss.hasPermi('microsoft:order:baseInfoList')")
@GetMapping("/baseInfoList")
public AjaxResult orderCusCollect() {
BaseInfoResponse baseInfoResponse = purchaseOrderService.orderCusCollect();
return AjaxResult.success(baseInfoResponse);
}
}
-------------------------------------------------------------------------------------------------------------
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
private static final Logger log = LoggerFactory.getLogger(PurchaseOrderServiceImpl.class);
@Autowired
private CusNameMapper cusNameMapper;
@Autowired
private ProductRefMapper productRefMapper;
@Override
public BaseInfoResponse orderCusCollect() {
BaseInfoResponse baseInfoResponse = new BaseInfoResponse();
List<CusName> cusNames = cusNameMapper.selectCusList();
if (!CollectionUtils.isEmpty(cusNames)) {
baseInfoResponse.setCusNameList(cusNames);
}
List<ProductRef> productRefs = productRefMapper.selectProductRefs();
if (!CollectionUtils.isEmpty(productRefs)) {
baseInfoResponse.setProductRefList(productRefs);
}
return baseInfoResponse;
}
}
-------------------------------------------------------------------------------------------------------------
public interface CusNameMapper {
List<CusName> selectCusList();
}
<mapper namespace="com.ekostar.microsoft.mapper.CusNameMapper">
<resultMap type="CusName" id="CusNameResult">
<result property="id" column="id" />
<result property="cusName" column="cus_name" />
<result property="createPer" column="create_per" />
<result property="createTime" column="create_time" />
<result property="isDeleted" column="is_deleted" />
</resultMap>
<select id="selectCusList" resultType="com.ekostar.microsoft.domain.CusName" resultMap="CusNameResult">
select id, cus_name, create_per, create_time
from ms_cus_name
where is_deleted = 1
</select>
</mapper>
CREATE TABLE `ms_cus_name` (
`id` bigint NOT NULL AUTO_INCREMENT,
`cus_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '客户名称',
`create_per` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`is_deleted` tinyint DEFAULT '1' COMMENT '逻辑删除状态;1-未删除;2-删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='客户名称表';
-------------------------------------------------------------------------------------------------------------
public interface ProductRefMapper {
List<ProductRef> selectProductRefs();
}
<mapper namespace="com.ekostar.microsoft.mapper.ProductRefMapper">
<resultMap type="ProductRef" id="ProductRefResult">
<result property="id" column="id" />
<result property="productName" column="product_name" />
<result property="sku" column="sku" />
<result property="isDeleted" column="is_deleted" />
<result property="returnable" column="returnable" />
<result property="unitPriceTaxBefore" column="unit_price_tax_before" />
</resultMap>
<select id="selectProductRefs" resultType="com.ekostar.microsoft.domain.ProductRef" resultMap="ProductRefResult">
select id, product_name, sku, returnable, unit_price_tax_before
from ms_product_ref
where is_deleted = 1
</select>
</mapper>
CREATE TABLE `ms_product_ref` (
`id` bigint NOT NULL AUTO_INCREMENT,
`product_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '产品名称',
`sku` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '产品型号',
`is_deleted` tinyint DEFAULT '1' COMMENT '逻辑删除状态:1-未删除;2-删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='产品对象表';
6 前端功能
6.1 按钮置灰
<template>
<div class="app-container">
<!-- 表格列表 -->
<el-table v-loading="loading" :data="orderList" stripe border>
<el-table-column label="PO单号" align="center" prop="poNumber" width="150px"/>
<el-table-column label="客户名称" align="center" prop="cusName" width="150px"/>
<el-table-column label="产品型号" align="center" prop="sku" width="100px"/>
<el-table-column label="产品名称" align="center" prop="productName" width="250px"/>
<el-table-column label="订单状态" align="center" prop="orderStatus" width="100px">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_order_status" :value="scope.row.orderStatus"/>
</template>
</el-table-column>
<el-table-column label="下单时间" align="center" prop="orderDate" width="140px">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.orderDate, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="num" width="auto"/>
<el-table-column label="单价-税前" align="center" prop="unitPriceTaxBefore" width="auto"/>
<el-table-column label="税率" align="center" prop="rate" width="auto"/>
<el-table-column label="税额" align="center" prop="tax" width="auto"/>
<el-table-column label="单价-税后" align="center" prop="unitPriceTaxAfter" width="auto"/>
<el-table-column label="总价-税前" align="center" prop="sumPriceTaxBefore" width="auto"/>
<el-table-column label="总价-税后" align="center" prop="sumPriceTaxAfter" width="auto"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="250px">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-shopping-cart-full"
@click="handlePurchase(scope.row)"
v-hasPermi="['microsoft:order:purchase']"
:disabled="scope.row.purchaseForbid"
>发送
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-s-grid"
@click="openImportTable(scope.row.id)"
v-hasPermi="['microsoft:order:tokenInfo']"
:disabled="scope.row.tokenForbid"
>详情
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['microsoft:order:edit']"
:disabled="scope.row.editForbid"
>修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['microsoft:order:remove']"
:disabled="scope.row.delForbid"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
-------------------------------------------------------------------------------------------------------------
export default {
name: 'Order',
components: { importTable },
dicts: ['sys_order_status', 'sys_fulfillment_type'],
data() {
return {
// 是否禁用:edit
editForbid: false,
// 是否禁用:del
delForbid: false,
// 是否禁用: purchase
purchaseForbid: false,
// 是否禁用:token
tokenForbid: false,
}
},
created() {
this.getList()
},
methods: {
// 列表
getList() {
// 刷新客户列表
this.getCusCollect()
this.loading = true
this.queryParams.params = {}
this.queryParams.beginOrderDate = null
this.queryParams.endOrderDate = null
this.queryParams.label = 1
if (null != this.daterangeOrderDate && '' != this.daterangeOrderDate) {
this.queryParams.beginOrderDate = this.daterangeOrderDate[0]
this.queryParams.endOrderDate = this.daterangeOrderDate[1]
}
listOrder(this.queryParams).then(response => {
if (response.rows !== null && response.rows !== undefined && response.rows.length > 0) {
response.rows.forEach(function(item) {
// 1,等待采购
// 2,采购完成
// 3,部分交付
// 4,全部交付
// 5,部分退货
// 6,全部退货
// 7,采购失败
// 8,退货失败
// false,启用
// true,禁用
if (item.orderStatus == 1) {
item.purchaseForbid = false
item.tokenForbid = true
item.editForbid = false
item.delForbid = false
} else if (item.orderStatus == 7) {
item.purchaseForbid = false
item.tokenForbid = false
item.editForbid = true
item.delForbid = true
} else {
item.purchaseForbid = true
item.tokenForbid = false
item.editForbid = true
item.delForbid = true
}
})
this.loading = false
this.orderList = response.rows
this.total = response.total
} else {
this.loading = false
this.orderList = []
// this.$modal.msgWarning('提示:数据不存在,或输入位置有误,请核对后再次查询!')
}
})
},
}
}
6.2 表格全选
<el-table v-loading="loading" :data="tokenList" stripe border max-height="380" @selection-change="handleSelectionChange" ref="dataTable2">
<el-table-column type="selection" width="55" align="center" :selectable="isSelectable"/>
-------------------------------------------------------------------------------------------------------------
this.$refs.dataTable2.toggleAllSelection()
// 全部勾选中,部分不能勾选
isSelectable(rows) {
// 1 已采购
// 2 已交付
// 3 已退货
// 退货 3不可以勾 1、2可以勾
// 交付 2、3不可以勾 1 可以勾
if (rows.status === 1) {
return true //可勾选
}
return false //不可勾选
}
<template>
<!-- 导入表 -->
<el-dialog :title="title" :visible.sync="visible" width="1100px" top="5vh" :show-close="showClo" :before-close="handleClose">
<!-- 搜索栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="90px">
<el-form-item label="TokenCode" prop="tokenCode">
<el-input
v-model.trim="queryParams.tokenCode"
placeholder="请输入TokenCode"
clearable
@input="$forceUpdate"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="TokenUrl" prop="tokenUrl">
<el-input
v-model.trim="queryParams.tokenUrl"
placeholder="请输入TokenUrl"
clearable
@input="$forceUpdate"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="Token状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择Token状态" clearable>
<el-option
v-for="dict in dict.type.sys_token_status2"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 表格列表 -->
<el-table v-loading="loading" :data="tokenList" stripe border max-height="380" @selection-change="handleSelectionChange" ref="dataTable2">
<el-table-column type="selection" width="55" align="center" :selectable="isSelectable"/>
<el-table-column label="序号" type="index" width="60" align="center"/>
<el-table-column label="TokenCode" align="center" prop="tokenCode" width="300"/>
<el-table-column label="TokenUrl" align="center" width="350">
<template v-if="scope.row.tokenUrl != null" slot-scope="scope">
<el-tooltip placement="top" x effect="light">
<div slot="content" class="tokenUrlClass">{{ scope.row.tokenUrl }}</div>
<div class="showname">{{ scope.row.tokenUrl.slice(35, 70) }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_token_status2" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="退货类型" prop="returnable" align="center" width="100">
<template slot-scope="scope">
<el-button plain size="mini" disabled type="warning" v-if="scope.row.returnable == '可退货'">可退货</el-button>
<el-button plain size="mini" disabled type="info" v-else>不可退货</el-button>
</template>
</el-table-column>
<el-table-column label="退货失败原因" prop="returnFailRea" align="center" width="180"/>
<el-table-column label="采购时间" align="center" prop="orderTime" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.orderTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="退货时间" align="center" prop="returnTime" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.returnTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="交付时间" align="center" prop="delTime" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.delTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" :disabled="multiple" @click="submitInfo2" v-hasPermi="['microsoft:order:info']">交 付</el-button>
<el-button @click="cancel">关 闭</el-button>
</div>
</el-dialog>
</template>
<script>
import { doInfo, doReturn, doToken, getOrder } from '@/api/microsoft/order'
export default {
name: 'ImportTable3',
dicts: ['sys_token_status2'],
data() {
return {
/** 弹框信息 */
title: '',
visible: false,
/** 搜索栏 */
// 查询参数
queryParams: {
orderId: null,
tokenCode: null,
tokenUrl: null,
status: null
},
// 显示搜索条件
showSearch: true,
/** 表格列表 */
// 遮罩层
// loading: true,
loading: false,
// Token状态表格数据
tokenList: [],
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
/** 分页 */
// 总条数
total: 0,
// 保存rowid
rowid: 0,
// 是否显示关闭按钮
showClo: true
}
},
methods: {
// 保存rowid
save3(id) {
this.rowid = id
// console.log(this.rowid)
},
// 显示弹框
show3() {
this.getList()
this.visible = true
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.tokenId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 搜索按钮操作 */
handleQuery() {
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
/** 表格列表 */
// 列表
getList() {
// 列表:PO单号
getOrder(this.rowid).then(response => {
this.title = 'PO单号:' + response.data.poNumber
}),
// 列表:PO单号 对应 Token
this.title = ''
this.tokenList = []
this.loading = true;
this.queryParams.orderId = this.rowid
doToken(this.queryParams).then(response => {
if (response.data !== null && response.data !== undefined && response.data.length > 0) {
this.tokenList = response.data
this.loading = false
} else {
this.tokenList = []
this.loading = false
// this.$modal.msgWarning('提示:数据不存在,或输入位置有误,请核对后再次查询!')
}
this.$refs.dataTable2.toggleAllSelection()
})
},
cancel() {
this.visible = false
this.queryParams = {}
},
handleClose() {
this.visible = false
this.queryParams = {}
},
// 交付
submitInfo2(row) {
const tokenIds = this.ids
this.$modal.confirm('是否交付?').then(() => {
this.multiple = true
this.loading = true
// this.$parent.$loading = true
doInfo(tokenIds).then(res => {
this.$message.success(res.msg)
this.getList()
this.$parent.getList()
this.loading = false
// this.$parent.$loading = false
this.visible = false
},
err => {
this.getList()
this.$parent.getList()
this.loading = false
// this.$parent.$loading = false
this.visible = false
}
)
// .catch(() => {
// this.loading = false
// this.visible = false
// this.getList()
// this.$parent.getList()
// })
})
},
// 全部勾选中,部分不能勾选
isSelectable(rows) {
// 1 已采购
// 2 已交付
// 3 已退货
// 退货 3不可以勾 1、2可以勾
// 交付 2、3不可以勾 1 可以勾
if (rows.status === 1) {
return true //可勾选
}
return false //不可勾选
}
}
}
</script>
<style lang="scss" scoped>
.tokenUrlClass {
width: 400px;
height: 125px;
}
</style>
7 发送邮件
7.1 依赖
<!--邮件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--freemarker模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
7.2 配置文件
spring:
mail:
default-encoding: utf-8
host: smtp.nantian.com.cn
password: NT2022abc
port: 465
username: esd-xlnt@nantian.com.cn
properties:
mail.smtp.auth: true
mail.smtp.timeout: 25000
mail.smtp.port: 465
mail.smtp.socketFactory.port: 465
mail.smtp.socketFactory.fallback: false
mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory
7.3 EmailUtil
@Component
public class EmailUtil {
@Autowired
private JavaMailSender javaMailSender;
// 发送方
@Value("${spring.mail.username}")
private String from;
// 接收方
@Value("${spring.mail.username}")
private String to;
/**
* 邮件发送
*
* @param subject 邮件主题
* @param content 邮件内容
* @param contentIsHtml 内容是否为html格式
* @param toMail 收件人邮箱
* @param ccMail 抄送人邮箱
* @param bccMail 秘密抄送人邮箱
* @param fileNames 邮箱附件
* @throws UnsupportedEncodingException
* @throws MessagingException
*/
public void sendEmail(String subject, String content, boolean contentIsHtml,String toMail, String ccMail, String bccMail, List<String> fileNames)
throws MessagingException, UnsupportedEncodingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(toMail);
if (!ObjectUtils.isEmpty(ccMail)) {
helper.setCc(ccMail);
}
if (!ObjectUtils.isEmpty(bccMail)) {
helper.setBcc(bccMail);
}
helper.setSubject(subject);
helper.setText(content, contentIsHtml);
if (!CollectionUtils.isEmpty(fileNames)) {
for (String fileName : fileNames) {
FileDataSource fileDataSource = new FileDataSource(fileName);
helper.addAttachment(fileDataSource.getName(), fileDataSource);
}
}
javaMailSender.send(message);
}
/**
* 邮件发送
*
* @param subject 邮件主题
* @param content 邮件内容
* @param contentIsHtml 内容是否为html格式
* @param toMail 收件人邮箱
* @param ccMail 抄送人邮箱
* @param bccMail 秘密抄送人邮箱
* @param files 邮箱附件
* @throws UnsupportedEncodingException
* @throws MessagingException
*/
public void sendEmail(String subject, String content, boolean contentIsHtml, String toMail, String ccMail, String bccMail, File[] files)
throws MessagingException, UnsupportedEncodingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(toMail);
if (!ObjectUtils.isEmpty(ccMail)) {
helper.setCc(ccMail);
}
if (!ObjectUtils.isEmpty(bccMail)) {
helper.setBcc(bccMail);
}
helper.setSubject(subject);
helper.setText(content, contentIsHtml);
// 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
if (!ObjectUtils.isEmpty(files)) {
for (File file : files) {
helper.addAttachment(file.getName(), file);
}
}
javaMailSender.send(message);
}
/**
* 邮件发送
*
* @param subject 邮件主题
* @param content 邮件内容
* @param contentIsHtml 内容是否为html格式
* @param fileName 文件名
* @param fileInput 邮箱附件
* @throws UnsupportedEncodingException
* @throws MessagingException
*/
public void sendEmail(String subject, String content, boolean contentIsHtml, String fileName, InputStreamSource fileInput) throws MessagingException, UnsupportedEncodingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, contentIsHtml);
if (fileInput != null) {
helper.addAttachment(fileName, fileInput);
}
javaMailSender.send(message);
}
}
7.4 ExcelUtils
@Component
public class ExcelUtils {
/**
* 生成excel文件
* @param dataList 数据列表
* @param clazz 导出对象类
* @return
* @throws IOException
*/
public static <T> ByteArrayOutputStream generateExcel(List<T> dataList, Class<T> clazz) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// excel写入
EasyExcel.write(out,clazz).sheet(0).doWrite(dataList);
return out;
}
}
7.5 发送附件邮件
public class MailTest {
@Test
public void test() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String format = simpleDateFormat.format(date);
String fileName = String.format("Office产品密钥-星链南天SO %s.xlsx", format);
try (ByteArrayOutputStream out = ExcelUtils.generateExcel(dataList, TokenForEmailVO.class)) {
// 生成excel文件
// 发送邮件
String subject = "订单交付//星链南天 SO //" + purchaseOrder.getCusName();
String content = "尊敬的客户:\n" +
"您好,附件是您采购的产品,敬请查收。\n" +
"星链南天 SO 单号:\n" +
"交付产品数量:" + tokenByIds.size() + "\n" +
"\n" +
"感谢您对微软产品和星链南天的支持与信任。\n" +
"如有问题,请随时与我们联系。";
emailUtil.sendEmail(subject, content, false, fileName, new ByteArrayResource(out.toByteArray()));
} catch (IOException e) {
log.error(String.format("生成excel失败,原因:%s", e));
e.printStackTrace();
} catch (MessagingException e) {
log.error(String.format("邮件发送失败,原因:%s", e));
e.printStackTrace();
}
}
}
8 HttpClient:redis设置token
8.1 配置文件
# 微软三方
ms:
# base地址
url: https://sandapac.channelinclusiontest.microsoft.com/channelinclusionREST.svc
# ChannelGuid
channelGuid: 7526bb6e-e0f1-4f41-a1b3-4571dd643f49
# timeout
timeout: 60
countrycode: CN
lang: zh-CN
storeid: N/A
# AAD认证
aad:
# 证书位置
pkcs12Certificate: D:\spark\xinlian\zi2\ekostar-admin\ekostar-sys-microsoft\src\main\resources\CIS_CISESD Yunnan Nantian China_New.pfx
# 证书密码
certificatePassword: NewPW!
# clientId
clientId: 6C41A07C-673E-4DB8-B172-F3E751007F75
# AzureActiveDirectoryInstance AAD获取认证令牌的实例
authority: https://login.microsoftonline.com/msretailfederationppe.onmicrosoft.com
# 静态声明应用程序级权限
scope: https://sandbox.esd.channelinclusion.microsoft.com/.default
8.2 MSApplicationConfig:配置类
@Configuration
public class MSApplicationConfig {
@Value("${ms.aad.pkcs12Certificate}")
private String pkcs12Certificate;
@Value("${ms.aad.certificatePassword}")
private String certificatePassword;
@Value("${ms.aad.clientId}")
private String clientId;
@Value("${ms.aad.authority}")
private String authority;
@Value("${ms.aad.scope}")
private String scope;
@Bean
public MSApplicationVo getFactoryInfo(){
MSApplicationVo applicationVo = new MSApplicationVo();
applicationVo.setPkcs12Certificate(pkcs12Certificate);
applicationVo.setCertificatePassword(certificatePassword);
applicationVo.setClientId(clientId);
applicationVo.setAuthority(authority);
applicationVo.setScope(scope);
return applicationVo;
}
}
8.3 AADTokenUtil:设置Token
@Component
public class AADTokenUtil {
private static String authenticationRedisKey = "AAD_Token_Authentication";
private static final Logger logger = LoggerFactory.getLogger(AADTokenUtil.class);
@Autowired
private MSApplicationConfig msApplicationConfig;
@Autowired
private RedisCache redisCache;
public IAuthenticationResult acquireToken() throws Exception {
logger.info("开始获取AAD_token验证信息(" + new Date() + ")");
MSApplicationVo applicationVo = msApplicationConfig.getFactoryInfo();
Set<String> scopes = new HashSet<>();
scopes.add(applicationVo.getScope());
InputStream inputStream = new FileInputStream(applicationVo.getPkcs12Certificate());
IClientCredential credential = ClientCredentialFactory.createFromCertificate(inputStream, applicationVo.getCertificatePassword());
ConfidentialClientApplication cca =
ConfidentialClientApplication
.builder(applicationVo.getClientId(), credential)
.authority(applicationVo.getAuthority())
.build();
IAuthenticationResult result;
try {
ClientCredentialParameters clientCredentialParameters = ClientCredentialParameters.builder(scopes).build();
result = cca.acquireToken(clientCredentialParameters).join();
String token = result.accessToken();
if (redisCache.hasKey(authenticationRedisKey)){
redisCache.deleteObject(authenticationRedisKey);
}
redisCache.setCacheObject(authenticationRedisKey, token, 60, TimeUnit.MINUTES);
logger.info("AAD_token验证信息:" + token);
logger.info("获取AAD_token验证信息结束(" + new Date() + ")");
} catch (Exception ex) {
if (ex.getCause() instanceof MsalException) {
ClientCredentialParameters parameters =
ClientCredentialParameters
.builder(scopes)
.build();
CompletableFuture<IAuthenticationResult> tt = cca.acquireToken(parameters);
result = tt.get();
} else {
throw ex;
}
}
return result;
}
}
8.4 AuthenticationThread:run()
@Component
public class AuthenticationThread extends Thread {
@Autowired
private AADTokenUtil aadTokenUtil;
public void run() {
Integer count = 0;
while (!this.isInterrupted()) {// 线程未中断执行循环
count++;
if (count == 6){ //刷新DNS
}
if (count >= 3){
try {
aadTokenUtil.acquireToken();
count = 0;
} catch (Exception e) {
e.printStackTrace();
}
}
try {
Thread.sleep(600000); //每隔十分钟执行一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
8.5 AuthenticationListener:启动线程
@Component
public class AuthenticationListener implements ServletContextListener {
private static String authenticationRedisKey = "AAD_Token_Authentication";
@Autowired
private AuthenticationThread authenticationThread;
@Autowired
private AADTokenUtil aadTokenUtil;
@Autowired
private RedisCache redisCache;
public void contextDestroyed(ServletContextEvent e) {
if (authenticationThread != null && authenticationThread.isInterrupted()) {
authenticationThread.interrupt();
}
}
public void contextInitialized(ServletContextEvent e) {
authenticationThread.start(); // servlet 上下文初始化时启动 socket
if (!redisCache.hasKey(authenticationRedisKey)) {
try {
aadTokenUtil.acquireToken();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
9 HttpClient:redis获取token
9.1 配置文件
# 微软三方
ms:
# base地址
url: https://sandapac.channelinclusiontest.microsoft.com/channelinclusionREST.svc
# ChannelGuid
channelGuid: 7526bb6e-e0f1-4f41-a1b3-4571dd643f49
# timeout
timeout: 60
countrycode: CN
lang: zh-CN
storeid: N/A
# AAD认证
aad:
# 证书位置
pkcs12Certificate: D:\spark\xinlian\zi2\ekostar-admin\ekostar-sys-microsoft\src\main\resources\CIS_CISESD Yunnan Nantian China_New.pfx
# 证书密码
certificatePassword: NewPW!
# clientId
clientId: 6C41A07C-673E-4DB8-B172-F3E751007F75
# AzureActiveDirectoryInstance AAD获取认证令牌的实例
authority: https://login.microsoftonline.com/msretailfederationppe.onmicrosoft.com
# 静态声明应用程序级权限
scope: https://sandbox.esd.channelinclusion.microsoft.com/.default
9.2 RedisCache
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value)
{
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
{
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout)
{
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit)
{
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获取有效时间
*
* @param key Redis键
* @return 有效时间
*/
public long getExpire(final String key)
{
return redisTemplate.getExpire(key);
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public Boolean hasKey(String key)
{
return redisTemplate.hasKey(key);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key)
{
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public boolean deleteObject(final Collection collection)
{
return redisTemplate.delete(collection) > 0;
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key)
{
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key)
{
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
{
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key)
{
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey)
{
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
{
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean deleteCacheMapValue(final String key, final String hKey)
{
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern)
{
return redisTemplate.keys(pattern);
}
}
9.3 RestTemplateConfig
@Configuration
public class RestTemplateConfig {
@Bean("restTemplate")
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(
MediaType.TEXT_HTML, //配了text/html
MediaType.TEXT_PLAIN,
MediaType.APPLICATION_XML,
MediaType.TEXT_XML)); //配了 text/plain
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
return restTemplate;
}
}
9.4 JsonUtil
public class JsonUtil {
/**
* 将xml转换为JSON对象
*
* @param xml xml字符串
* @return
*/
public static JSONObject xmlToJson(String xml) throws DocumentException {
JSONObject jsonObject = new JSONObject();
Document document = DocumentHelper.parseText(xml);
//获取根节点元素对象
Element root = document.getRootElement();
iterateNodes(root, jsonObject);
return jsonObject;
}
/**
* 遍历元素
*
* @param node 元素
* @param json 将元素遍历完成之后放的JSON对象
*/
public static void iterateNodes(Element node, JSONObject json) {
//获取当前元素的名称
String nodeName = node.getName();
//判断已遍历的JSON中是否已经有了该元素的名称
if (json.containsKey(nodeName)) {
//该元素在同级下有多个
Object Object = json.get(nodeName);
JSONArray array = null;
if (Object instanceof JSONArray) {
array = (JSONArray) Object;
} else {
array = new JSONArray();
array.add(Object);
}
//获取该元素下所有子元素
List<Element> listElement = node.elements();
if (listElement.isEmpty()) {
//该元素无子元素,获取元素的值
String nodeValue = node.getTextTrim();
array.add(nodeValue);
json.put(nodeName, array);
return;
}
//有子元素
JSONObject newJson = new JSONObject();
//遍历所有子元素
for (Element e : listElement) {
//递归
iterateNodes(e, newJson);
}
array.add(newJson);
json.put(nodeName, array);
return;
}
//该元素同级下第一次遍历
//获取该元素下所有子元素
List<Element> listElement = node.elements();
if (listElement.isEmpty()) {
//该元素无子元素,获取元素的值
String nodeValue = node.getTextTrim();
json.put(nodeName, nodeValue);
return;
}
//有子节点,新建一个JSONObject来存储该节点下子节点的值
JSONObject object = new JSONObject();
//遍历所有一级子节点
for (Element e : listElement) {
//递归
iterateNodes(e, object);
}
json.put(nodeName, object);
return;
}
}
9.5 HttpClientUtil
@Component
public class HttpClientUtil {
private static String authenticationRedisKey = "AAD_Token_Authentication";
@Value("${ms.url}")
private String msUrl;
@Value("${ms.timeout}")
private long msTimeOut;
@Autowired
private RestTemplateConfig restTemplateConfig;
@Autowired
private RedisCache redisCache;
/**
* 获取redis中存储的Token(AAD认证)
*/
private String getTokenInfo() {
if (!redisCache.hasKey(authenticationRedisKey)) {
try {
throw new Exception("AAD认证信息获取失败!");
} catch (Exception e) {
e.printStackTrace();
}
}
String token = redisCache.getCacheObject(authenticationRedisKey);
return token;
}
/**
* 发起GET请求
*
* @param url 请求链接
* @param params 请求参数
* @param c 请求输入类型
* @return
* @param <T>
*/
public <T> T get(String url, Map<String, Object> params, Class<T> c) {
RestTemplate restTemplate = restTemplateConfig.restTemplate();
HttpHeaders headers = new HttpHeaders();
String token = getTokenInfo();
// 设置BearerAuth,即Token
headers.setBearerAuth(token);
// 设置ContentType,即application,x-www-form-urlencoded
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity httpEntity = new HttpEntity(null, headers);
if (null == params || params.isEmpty()) {
return restTemplate.exchange(msUrl + url, HttpMethod.GET, httpEntity, c).getBody();
} else {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(msUrl + url);
params.forEach((k, v) -> {
builder.queryParam(k, v);
});
return restTemplate.exchange(builder.build().toString(), HttpMethod.GET, httpEntity, c, params).getBody();
}
}
/**
* 发起POST请求
*
* @param url 请求链接
* @param params 请求参数
* @param c 请求输入类型
* @return
* @param <T>
*/
public <T> T post(String url, Map<String, Object> params, Class<T> c) {
RestTemplate restTemplate = restTemplateConfig.restTemplate();
HttpHeaders headers = new HttpHeaders();
String token = getTokenInfo();
// 设置BearerAuth,即Token
headers.setBearerAuth(token);
// 设置ContentType
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity httpEntity = new HttpEntity(params, headers);
if (null == params || params.isEmpty()) {
return restTemplate.exchange(msUrl + url, HttpMethod.POST, httpEntity, c).getBody();
} else {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(msUrl + url);
params.forEach(builder::queryParam);
return restTemplate.exchange(builder.build().toString(), HttpMethod.POST, httpEntity, c, params).getBody();
}
}
/**
* 发起携带XML内容 的 POST请求
*
* @param url 请求链接
* @param xmlData 序列化字符串
* @return
*/
public String sendPostXmlRequest(String url, String xmlData) {
RestTemplate restTemplate = restTemplateConfig.restTemplate();
HttpHeaders headers = new HttpHeaders();
String token = getTokenInfo();
// 设置BearerAuth,即Token
headers.setBearerAuth(token);
// 设置ContentType
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> entity = new HttpEntity<>(xmlData, headers);
String result = restTemplate.postForObject(msUrl + url, entity, String.class);
return result;
}
}
9.6 发起GET请求:获取Catalog
@Service
public class ProductCatalogServiceImpl implements IProductCatalogService {
@Autowired
private ProductCatalogMapper productCatalogMapper;
@Autowired
private HttpClientUtil httpClientUtil;
@Value("${ms.lang}")
private String lang;
/**
* 查询产品目录列表
*
* @param productCatalog 产品目录
* @return 产品目录
*/
@Override
public List<ProductCatalog> catalogList(ProductCatalog productCatalog) throws Exception {
/**
* 请求微软API,获取产品目录数据,插入数据库
*/
String sync = catalogSync();
if ("4003".equals(sync)){
throw new Exception("微软AAD认证信息失效!");
}
return productCatalogMapper.selectProductCatalogList(productCatalog);
}
/**
* 请求微软API,获取产品目录数据,插入数据库
*/
@Override
public String catalogSync() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
long l = (System.currentTimeMillis()) - (1000L * 60 * 60 * 24 * 30 * 3);
//long l = System.currentTimeMillis();
Date date = new Date(l);
// 请求参数
String utcUpdatesFrom = formatter.format(date);
// 获取目录请求
Map<String, Object> map = new HashMap<>();
map.put("utcUpdatesFrom", utcUpdatesFrom);
map.put("pg", 1);
map.put("lang", lang);
String url = "/v3_1/catalog";
String xmlString = null;
try {
xmlString = httpClientUtil.get(url, map, String.class);
} catch (Exception e) {
if (e.getMessage().contains("4003")){
return "4003";
}
}
// 清空表
productCatalogMapper.truncateTable();
try {
// 解析xml
JSONObject jsonObject = JsonUtil.xmlToJson(xmlString);
String jsonData = jsonObject.toString();
JSONObject parse = JSONObject.parse(jsonData);
List<ProductCatalog> productCatalogList = new ArrayList<>();
JSONArray catalogChange = null;
if (parse != null) {
// 获取根节点
parse = parse.getJSONObject("CatalogResult");
//获取当前页
String currentPageNum = parse.getString("CurrentPageNum");
//获取 目录请求的开始时间
Date utcUpdatesFrom1 = parse.getDate("UtcUpdatesFrom");
//获取 最近一次目录请求的完成时间
Date utcUpdatesTo = parse.getDate("UtcUpdatesTo");
parse = parse.getJSONObject("CatalogEntries");
// 获取对象数组中的数据
catalogChange = parse.getJSONArray("CatalogChange");
for (Object feature : catalogChange) {
JSONObject featureObject = (JSONObject) feature;
JSONObject catalogMeta = featureObject.getJSONObject("CatalogMeta");
ProductCatalog productCatalog = new ProductCatalog();
//传给ProductCatalog
productCatalog.setUtcUpdatesFrom(utcUpdatesFrom1);
productCatalog.setUtcUpdatesTo(utcUpdatesTo);
productCatalog.setPage(currentPageNum);
productCatalog.setLanguageLocale("zh-CN");
productCatalog.setSku(catalogMeta.getString("Sku"));
productCatalog.setReturnType( catalogMeta.getString("ReturnType"));
productCatalog.setFullTitle(catalogMeta.getString("FullTitle"));
productCatalog.setDescription(catalogMeta.getString("Description"));
productCatalog.setFulfillmentType(catalogMeta.getString("FulfillmentType"));
// 获取Pricing的json对象
JSONObject pricing = catalogMeta.getJSONObject("Pricing");
// 获取Price的json对象,以提取此中的数据
JSONObject price = pricing.getJSONObject("Price");
productCatalog.setPricing(price.getBigDecimal("Amount"));
productCatalog.setCurrency(price.getString("Currency"));
productCatalog.setValidFrom(price.getDate("ValidFrom"));
productCatalog.setValidTo(price.getDate("ValidTo"));
productCatalogList.add(productCatalog);
}
/**
* 批量插入
*/
productCatalogMapper.insertProductCatalog(productCatalogList);
}
return "200";
} catch (DocumentException e) {
e.printStackTrace();
}
return "500";
}
}
9.7 发起GET请求:更新Token
@Service
public class TokenServiceImpl implements ITokenService {
@Autowired
private TokenMapper tokenMapper;
@Autowired
private ProductRefMapper productRefMapper;
@Autowired
private PurchaseOrderMapper purchaseOrderMapper;
@Autowired
private HttpClientUtil httpClientUtil;
/**
* 查询Token状态列表
*
* @param token Token状态
* @return Token状态
*/
@Override
public List<Token> tokenList(Token token) throws Exception{
List<Token> tokenList = tokenMapper.selectTokenList(token);
/**
* 请求微软API,检查token状态
*/
List<Token> resultList = tokenStatus(tokenList);
return resultList;
}
/**
* 请求微软API,检查token状态
*
* @param tokenList Token状态列表
* @return token更新成功与否
*/
public List<Token> tokenStatus(List<Token> tokenList) throws Exception {
Map<String, Object> map = new HashMap<>();
String ctid = null, token = null;
if (!CollectionUtils.isEmpty(tokenList)) {
for (Token value : tokenList) {
ctid = value.getClientTransactionId();
token = value.getTokenCode();
map.put("ctid", ctid);
map.put("token", token);
String url = "/v3/status";
String xmlString = null;
try {
/**
* httpClient发起Get请求,得到【xmlString】字符串
*/
xmlString = httpClientUtil.get(url, map, String.class);
} catch (Exception e) {
if (e.getMessage().contains("4003")){
throw new Exception("微软AAD认证信息失效!");
}
}
JSONObject jsonObject = null;
try {
/**
* 对【xmlString】字符串进行XML解析
*/
jsonObject = JsonUtil.xmlToJson(xmlString);
String jsonData = jsonObject.toString();
JSONObject parse = JSONObject.parse(jsonData);
/**
* 解析成功后,对 每个Token 进行 Set属性赋值
*/
if (parse != null) {
// 获取根节点
parse = parse.getJSONObject("TokenInfo");
value.setLastUpdateofStatus(parse.getDate("LastUpdateOfStatus"));
value.setPromotionName(parse.getString("PromotionName"));
value.setRedemptionDateTime(parse.getDate("RedemptionDateTime"));
value.setTokenClassName(parse.getString("TokenClassName"));
value.setTokenStatus(parse.getString("TokenStatus"));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 批量更新token数据
*/
tokenMapper.updateBatchToken(tokenList);
}
return tokenList;
}
}
9.8 发起POST请求:退货
/**
* 向微软退货申请 发送xml形式内容
*/
public class TokenReturnRequest {
//客户交易ID
private String clientTransactionId;
//token code
private String code;
//固定值GUID,微软提供ChannelGuid
private String billToAccountId;
public String getClientTransactionId() {
return clientTransactionId;
}
public void setClientTransactionId(String clientTransactionId) {
this.clientTransactionId = clientTransactionId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getBillToAccountId() {
return billToAccountId;
}
public void setBillToAccountId(String billToAccountId) {
this.billToAccountId = billToAccountId;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("<TokenReturnRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.datacontract.org/2004/07/LOE.Common.Contracts.Fulfillment.V3\">");
sb.append("<RequestContext>");
sb.append("<ClientTransactionId>").append(getClientTransactionId()).append("</ClientTransactionId>");
sb.append("<PartnerAttributes xsi:nil=\"true\" />");
sb.append("</RequestContext>");
sb.append("<Token>");
sb.append("<Code>").append(getCode()).append("</Code>");
sb.append("</Token>");
sb.append("<Billing>");
sb.append("<BillToAccountId>").append(getBillToAccountId()).append("</BillToAccountId>");
sb.append("<PurchaseOrderId xsi:nil=\"true\" />");
sb.append("</Billing>");
sb.append("</TokenReturnRequest>");
return sb.toString();
}
}
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
@Transactional(rollbackFor = Exception.class)
@Override
public AjaxResult orderReturn(List<Long> tokenId, String operName) {
List<Token> tokenList = tokenMapper.selectTokenByIds(tokenId);
List<Token> tokenStatusList = new ArrayList<>();
for (Token token : tokenList) {
Token token1 = new Token();
BeanUtils.copyProperties(token, token1);
tokenStatusList.add(token1);
}
Map<Long, Token> tokenMap = tokenStatusList.stream().collect(Collectors.toMap(m -> m.getTokenId(), m -> m));
if (!CollectionUtils.isEmpty(tokenList)) {
Token token1 = tokenList.get(0);
PurchaseOrder purchaseOrder = purchaseOrderMapper.selectPurchaseOrderById(token1.getOrderId());
purchaseOrder.setOrderStatus(null);
Integer count = 0;
Integer num = 0;
Boolean isAll = true;
Boolean aadEx = true;
for (Token token : tokenList) {
if (token.getStatus() != null && !token.getStatus().equals(3)) {
String url = "/v3/tokens/return";
// 解析xml
JSONObject jsonObject = null;
// 退货异常捕获
try {
// 多个退货
TokenReturnRequest tokenReturnRequest = new TokenReturnRequest();
tokenReturnRequest.setCode(token.getTokenCode());
tokenReturnRequest.setClientTransactionId(token.getClientTransactionId());
tokenReturnRequest.setBillToAccountId(channelGuid);
//添加到集合
String requestStr = tokenReturnRequest.toString();
/**
* httpClient发起POST请求,得到【xmlData】字符串
*/
String xmlData = httpClientUtil.sendPostXmlRequest(url, requestStr);
try {
jsonObject = JsonUtil.xmlToJson(xmlData);
String jsonData = jsonObject.toString();
//获取返回成功xml数据
JSONObject parseForSuccess = JSONObject.parse(jsonData);
if (parseForSuccess != null) {
//System.out.println(parseForSuccess);
parseForSuccess = parseForSuccess.getJSONObject("TokenReturnResponse");
parseForSuccess = parseForSuccess.getJSONObject("ResponseContext");
String clientTransactionId = parseForSuccess.getString("ClientTransactionId");
String serviceTransactionId = parseForSuccess.getString("ServiceTransactionId");
token.setTokenStatus("Invalid");
token.setReturnMan(operName);
token.setReturnTime(new Date());
token.setStatus(3);
// purchaseOrder.setOrderStatus(isAll ? 6L : 5L); //部分、全部
}
} catch (DocumentException e) {
log.error("系统异常:" + e);
token.setReturnFailRea("系统异常");
token.setReturnMan(operName);
token.setReturnTime(new Date());
purchaseOrder.setOrderStatus(8L);
continue;
}
} catch (Exception e) {
String messageInfo = e.getMessage();
if (messageInfo != null) {
// 认证失败异常
if (messageInfo.contains("4003")) {
aadEx = false;
String messageForRes = messageInfo.substring(16, e.getMessage().length() - 1);
System.out.println(messageForRes);
String message = "AAD认证信息过期";
token.setReturnFailRea(message);
token.setReturnMan(operName);
token.setReturnTime(new Date());
log.error("===========INFO===== " + 4003 + ": " + message);
} else {
try {
String substring = messageInfo.substring(messageInfo.indexOf("<Fault"), messageInfo.lastIndexOf("\""));
jsonObject = JsonUtil.xmlToJson(substring);
} catch (DocumentException ex) {
ex.printStackTrace();
}
String jsonData = jsonObject.toString();
JSONObject parse = JSONObject.parse(jsonData);
if (parse != null) {
parse = parse.getJSONObject("Fault");
parse = parse.getJSONObject("Detail");
parse = parse.getJSONObject("PartnerRESTServiceFault");
// 异常数据 错误码 错误信息
String errorCode = parse.getString("ErrorCode");
String message = parse.getString("Message");
token.setReturnMan(operName);
token.setReturnTime(new Date());
errorMsg(token, message, errorCode);
num++;
}
if (StringUtils.isEmpty(token.getReturnFailRea())) {
// network error
token.setReturnFailRea("Read timed out");
token.setReturnMan(operName);
token.setReturnTime(new Date());
log.error("===========INFO===== " + "Read timed out");
count++;
purchaseOrder.setOrderStatus(8L);
}
}
continue;
}
}
}
}
for (Token token : tokenList) {
token.setEmailStatus(1);
}
tokenMapper.updateBatchToken(tokenList);
//校验是否全部
List<Token> tokens = tokenMapper.selectByOrderId(token1.getOrderId());
for (Token token : tokens) {
if (token.getStatus().equals(1) || token.getStatus().equals(2)) {
isAll = false;
}
}
if (purchaseOrder.getOrderStatus() == null) {
purchaseOrder.setOrderStatus(isAll ? 6L : 5L); //部分、全部
}
purchaseOrder.setReturnTime(new Date());
purchaseOrder.setReturnMan(operName);
purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
if (count > 0) {
if (!aadEx) {
return AjaxResult.error("因微软AAD认证信息失效,本次操作有" + count + "条退货失败,可重新发起退货!");
}
return AjaxResult.error("本次操作有" + count + "条退货失败,可重新发起退货!");
}
}
return AjaxResult.error("退货申请失败!");
}
}
10 后端功能1
10.1 日志使用
方式一:
import org.slf4j.LoggerFactory;
public class XXXXXX {
private static final Logger log = LoggerFactory.getLogger(XXXXXX.class); //第1种
private final Logger log = LoggerFactory.getLogger(this.getClass()); //第2种
}
方式二:slf4j(lombok)提供了日志接口、获取具体日志对象的方法,日志级别由高到底是:fatal -> error -> warn -> info -> debug
@Slf4j
public class CommonController {
log.info("启用禁用员工账号:{}{}", status, id);
log.error("文件上传失败:{}", e);
log.debug("debug");
log.warn("warn");
log.fatal("fatal");
}
10.2 常量使用
/**
* 状态常量,启用或者禁用
*/
public class StatusConstant {
//启用
public static final Integer ENABLE = 1;
//禁用
public static final Integer DISABLE = 0;
}
-------------------------------------------------------------------------------------------------------------
category.setStatus(StatusConstant.DISABLE);
public class MessageConstant {
public static final String PASSWORD_ERROR = "密码错误";
public static final String ACCOUNT_NOT_FOUND = "账号不存在";
public static final String ACCOUNT_LOCKED = "账号被锁定";
public static final String ALREADY_EXISTS = "已存在";
}
10.3 枚举使用
package com.ekostar.microsoft.enums;
/**
* @author: Jason
* @date: 2023/1/18 9:55
* @description: 退货响应
*/
public enum ReturnStatus {
RETURN_CODE_ACKNOWLEDGED("n/a", "已接受请求但尚未处理或者不适用"),
RETURN_CODE_PROPERTY("6", "合作伙伴属性内容超过允许的最大长度"),
RETURN_CODE_DEACTIVATED("3002", "令牌已停用"),
RETURN_CODE_REDEEMED("3003", "令牌已兑换"),
RETURN_CODE_BLACKLISTED("3006", "令牌已被列入黑名单"),
RETURN_CODE_EXPIRED("3007", "令牌已过期"),
//RETURN_CODE_NA("n/a", "n/a"),
RETURN_CODE_NETWORK_ERROR("0", "服务中发生内部错误"),
RETURN_CODE_ERROR("4001", "未找到令牌或订单详细信息尚不可用"),
RETURN_CODE_AUTHERROR("4003", "授权失败"),
RETURN_CODE_GUID("4008", "客户端事务 ID 可能不是空的 GUID"),
RETURN_CODE_MICROSOFT("4010", "令牌不能根据您与微软签订的合同退还(停用)"),
RETURN_CODE_NOT_ESD("5004", "令牌不是通过 ESD 订购的"),
RETURN_CODE_ACC_MISMATCH("5005", "提供的 BillToAccountId 与最初订购令牌的帐户不匹配"),
RETURN_CODE_XSD("6001", "语法错误:<<XSD 验证错误>>"),
RETURN_CODE_BTAID("6002", "BillToAccountId 为空或无效"),
RETURN_CODE_INCONFORMITY("6003", "相关产品或优惠不符合退货条件"),
RETURN_CODE_NOT_FOUND("6004", "未找到关联产品或不再可用(不符合退货条件或商品不符合退货条件时退货)");
private String code;
private String message;
ReturnStatus() {
}
ReturnStatus(String message) {
this.message = message;
}
ReturnStatus(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* @param token Token对象
* @param message 退货详情信息
* @param errorCode 错误码
*/
private void errorMsg(Token token, String message, String errorCode) {
if (ReturnStatus.RETURN_CODE_ACKNOWLEDGED.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_ACKNOWLEDGED.getMessage());
}
if (ReturnStatus.RETURN_CODE_PROPERTY.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_PROPERTY.getMessage());
}
if (ReturnStatus.RETURN_CODE_DEACTIVATED.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_DEACTIVATED.getMessage());
}
if (ReturnStatus.RETURN_CODE_REDEEMED.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_REDEEMED.getMessage());
token.setTokenStatus("Redeemed"); // 已兑换
}
if (ReturnStatus.RETURN_CODE_BLACKLISTED.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_BLACKLISTED.getMessage());
token.setTokenStatus("Blacklisted"); // 黑名单
}
if (ReturnStatus.RETURN_CODE_EXPIRED.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_EXPIRED.getMessage());
token.setTokenStatus("Invalid"); // 失效
}
if (ReturnStatus.RETURN_CODE_NETWORK_ERROR.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_NETWORK_ERROR.getMessage());
token.setTokenStatus("Unknown"); // 未知
}
if (ReturnStatus.RETURN_CODE_ERROR.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_ERROR.getMessage());
}
if (ReturnStatus.RETURN_CODE_GUID.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_GUID.getMessage());
}
if (ReturnStatus.RETURN_CODE_MICROSOFT.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_MICROSOFT.getMessage());
}
if (ReturnStatus.RETURN_CODE_NOT_ESD.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_NOT_ESD.getMessage());
}
if (ReturnStatus.RETURN_CODE_ACC_MISMATCH.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_ACC_MISMATCH.getMessage());
}
if (ReturnStatus.RETURN_CODE_XSD.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_XSD.getMessage());
}
if (ReturnStatus.RETURN_CODE_BTAID.getCode().equals(errorCode)) {
token.setReturnFailRea(message);
}
if (ReturnStatus.RETURN_CODE_INCONFORMITY.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_INCONFORMITY.getMessage());
}
if (ReturnStatus.RETURN_CODE_NOT_FOUND.getCode().equals(errorCode)) {
token.setReturnFailRea(ReturnStatus.RETURN_CODE_NOT_FOUND.getMessage());
}
}
ReturnStatus.RETURN_CODE_ACKNOWLEDGED.getCode()
ReturnStatus.RETURN_CODE_ACKNOWLEDGED.getMessage()
-------------------------------------------------------------------------------------------------------------
ReturnStatus.RETURN_CODE_ACKNOWLEDGED.setCode("0000");
ReturnStatus.RETURN_CODE_ACKNOWLEDGED.setMessage("0000对应代码描述");
10.4 拷贝属性
@Override
public PageDTO<LearningLessonVO> queryMyLessons(PageQuery query) {
// 1.获取当前登录用户
Long userId = UserContext.getUser();
// 2.分页查询
// select * from learning_lesson where user_id = #{userId} order by latest_learn_time limit 0, 5
Page<LearningLesson> page = lambdaQuery()
.eq(LearningLesson::getUserId, userId) // where user_id = #{userId}
.page(query.toMpPage("latest_learn_time", false));
List<LearningLesson> records = page.getRecords();
if (CollUtils.isEmpty(records)) {
return PageDTO.empty(page);
}
// 3.查询课程信息
Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
// 4.封装VO返回
List<LearningLessonVO> list = new ArrayList<>(records.size());
// 4.1.循环遍历,把LearningLesson转为VO
for (LearningLesson r : records) {
// 4.2.拷贝基础属性到vo
LearningLessonVO vo = BeanUtils.copyBean(r, LearningLessonVO.class);
// 4.3.获取课程信息,填充到vo
CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
vo.setCourseName(cInfo.getName());
vo.setCourseCoverUrl(cInfo.getCoverUrl());
vo.setSections(cInfo.getSectionNum());
list.add(vo);
}
return PageDTO.of(page, list);
}
@Override
public List<OrderForTokenListVO> orderList(PurchaseOrderRequest purchaseOrder, Integer label) {
List<PurchaseOrder> purchaseOrderList = purchaseOrderMapper.selectOrderList(purchaseOrder, label);
List<OrderForTokenListVO> orderForTokenListVOS = new ArrayList<>();
for (PurchaseOrder order : purchaseOrderList) {
// 拷贝基础属性到vo
OrderForTokenListVO orderForTokenListVO = new OrderForTokenListVO();
BeanUtil.copyProperties(order, orderForTokenListVO);
orderForTokenListVOS.add(orderForTokenListVO);
}
return orderForTokenListVOS;
}
@Override
public List<TokenResponse> orderGetTokenInfo(Token token) {
List<Token> tokenList = tokenMapper.findTokensById(token);
List<TokenResponse> resultList = new ArrayList<>();
for (Token item : tokenList) {
// 拷贝基础属性到vo
TokenResponse response = new TokenResponse();
BeanUtil.copyProperties(item, response);
if (returnable != null){
response.setReturnable(returnable == 1 ? "可退货" : "不可退货");
}
resultList.add(response);
}
return resultList;
}
public void insert(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//对象属性拷贝
BeanUtils.copyProperties(employeeDTO, employee);
//设置账号的状态,默认正常状态 1表示正常 0表示锁定
employee.setStatus(StatusConstant.ENABLE);
//设置密码,默认密码123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
employeeMapper.insert(employee);
}
10.5 Stream:list、set、map
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class Test01 {
@Test
public void test1(){
List<LearningLesson> list = new ArrayList<>();
LearningLesson Lesson1 = new LearningLesson();
Lesson1.setId(1L);
Lesson1.setCourseId(1L);
LearningLesson Lesson2 = new LearningLesson();
Lesson2.setId(2L);
Lesson2.setCourseId(2L);
list.add(Lesson1);
list.add(Lesson2);
System.out.println(list);
// 使用 for循环 获取集合中所有的learningLesson的id值
List<Long> ids1 = new ArrayList<>();
for (LearningLesson lesson : list){
ids1.add(lesson.getId());
}
// 使用 stream流 获取集合中所有的learningLesson的id值
List<Long> ids2 = list.stream().map(LearningLesson::getId).collect(Collectors.toList());
Set<Long> ids3 = list.stream().map(LearningLesson::getId).collect(Collectors.toSet());
System.out.println(ids1);
System.out.println(ids2);
System.out.println(ids3);
// 使用 for循环 对List转map
Map<Long,LearningLesson> map = new HashMap<>();
for (LearningLesson lesson : list){
map.put(lesson.getId(), lesson);
}
// 使用 stream流 对List转map
Map<Long, LearningLesson> LessonMap = list.stream().collect(Collectors.toMap(LearningLesson::getId, c->c));
System.out.println(LessonMap);
}
}
-------------------------------------------------------------------------------------------------------------
[LearningLesson(id=1, userId=null, courseId=1, status=null, weekFreq=null, planStatus=null, learnedSections=null, latestSectionId=null, latestLearnTime=null, createTime=null, expireTime=null, updateTime=null), LearningLesson(id=2, userId=null, courseId=2, status=null, weekFreq=null, planStatus=null, learnedSections=null, latestSectionId=null, latestLearnTime=null, createTime=null, expireTime=null, updateTime=null)]
[1, 2]
[1, 2]
[1, 2]
{1=LearningLesson(id=1, userId=null, courseId=1, status=null, weekFreq=null, planStatus=null, learnedSections=null, latestSectionId=null, latestLearnTime=null, createTime=null, expireTime=null, updateTime=null), 2=LearningLesson(id=2, userId=null, courseId=2, status=null, weekFreq=null, planStatus=null, learnedSections=null, latestSectionId=null, latestLearnTime=null, createTime=null, expireTime=null, updateTime=null)}
10.6 UserMapper:直接测试Mapper
public class UserMapperTest {
public static UserMapper mapper;
@BeforeClass
public static void setUpMybatisDatabase() {
SqlSessionFactory builder = new SqlSessionFactoryBuilder()
.build(UserMapperTest.class
.getClassLoader()
.getResourceAsStream("mybatisTestConfiguration/UserMapperTestConfiguration.xml")
);
mapper = builder.getConfiguration().getMapper(UserMapper.class, builder.openSession(true));
}
@Test
public void testSelectByPrimaryKey() {
User user = mapper.selectByPrimaryKey(1L);
System.out.println(user);
}
}
-------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Mybatis config sample -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default = "default">
<environment id="default">
<transactionManager type="JDBC"/>
<dataSource type="UNPOOLED">
<property name = "driver" value = "com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mytest2?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
10.7 PostMapperTest:@Autowired测试Mapper
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class PostMapperTest2 {
@Autowired
private PostMapper mapper;
@Test
public void testSelectByPrimaryKey() {
Post post = mapper.selectByPrimaryKey(1L);
System.out.println(post);
}
@Test
public void testinsertSelective() {
Post post = new Post();
post.setUserId(1L);
post.setTitle("文章12文章12文章14");
post.setContent("内容12内容12内容12内容13");
post.setDescription("描述12描述12描述13");
post.setStatus(0);
post.setCreated(new Date());
post.setModified(new Date());
mapper.insertSelective(post);
System.out.println(post.getId());
}
}
11 后端功能2
11.1 单个注值
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
@Value("${ms.storeid}")
private String storeid;
@Value("${ms.countrycode}")
private String countrycode;
@Override
public AjaxResult orderPurchase(Long id, String operName) {
for (int i = 0; i < orderNum; i++) {
Map<String, Object> map = new HashMap<>();
ctid = UUID.randomUUID().toString();
map.put("ctid", ctid);
map.put("sku", sku);
map.put("countrycode", countrycode); // 使用countrycode
map.put("storeid", storeid); // 使用storeid
map.put("resellerid", resellerid);
alist.add(map);
//System.out.println(map.values());
url = "/v3/Tokens";
}
}
}
11.2 逻辑删除
@Api("订单接口")
@RestController
@RequestMapping("/microsoft/order")
public class PurchaseOrderController extends BaseController {
/**
* 删除订单
*/
@PreAuthorize("@ss.hasPermi('microsoft:order:remove')")
@Log(title = "订单", businessType = BusinessType.DELETE)
@DeleteMapping("/delete/{ids}")
public AjaxResult orderRemove(@PathVariable Long[] ids) {
return toAjax(purchaseOrderService.orderRemove(ids));
}
}
-------------------------------------------------------------------------------------------------------------
public interface IPurchaseOrderService {
/**
* 批量删除订单
*
* @param ids 需要删除的订单主键集合
* @return 结果
*/
int orderRemove(Long[] ids);
/**
* 删除订单信息
*
* @param id 订单主键
* @return 结果
*/
int deletePurchaseOrderById(Long id);
}
@Service
public class PurchaseOrderServiceImpl implements IPurchaseOrderService {
private static final Logger log = LoggerFactory.getLogger(PurchaseOrderServiceImpl.class);
/**
* 批量删除订单
*
* @param ids 需要删除的订单主键
* @return 结果
*/
@Override
public int orderRemove(Long[] ids) {
return purchaseOrderMapper.deletePurchaseOrderByIds(ids);
}
/**
* 删除订单信息
*
* @param id 订单主键
* @return 结果
*/
@Override
public int deletePurchaseOrderById(Long id) {
return purchaseOrderMapper.deletePurchaseOrderById(id);
}
}
-------------------------------------------------------------------------------------------------------------
public interface PurchaseOrderMapper {
/**
* 删除
*
* @param id 订单主键
* @return 结果
*/
int deletePurchaseOrderById(Long id);
/**
* 批量删除
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deletePurchaseOrderByIds(Long[] ids);
}
<mapper namespace="com.ekostar.microsoft.mapper.PurchaseOrderMapper">
<delete id="deletePurchaseOrderById" parameterType="Long">
update ms_purchase_order set is_deleted=2 where id = #{id}
</delete>
<delete id="deletePurchaseOrderByIds" parameterType="String">
update ms_purchase_order set is_deleted=2 where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
public interface PurchaseOrderMapper {
/**
* 查询 未删除和订单状态 订单列表
* @param purchaseOrder 订单对象
* @param label 订单状态范围
* @return
*/
List<PurchaseOrder> selectOrderList(@Param("purchaseOrder") PurchaseOrderRequest purchaseOrder, @Param("label") Integer label);
}
<mapper namespace="com.ekostar.microsoft.mapper.PurchaseOrderMapper">
<select id="selectOrderList" resultMap="PurchaseOrderResult">
<include refid="selectPurchaseOrderVo"/>
<where>
is_deleted = 1 // 逻辑删除
<if test="label == 2"> and order_status > 1 and order_status != 7</if> // 交付页面 label 1.订单 2.交付 3.退货
<if test="label == 3"> and order_status > 1 and order_status != 7</if> // 退货页面 label 1.订单 2.交付 3.退货
<if test="purchaseOrder.poNumber != null and purchaseOrder.poNumber != ''"> and po_number like concat('%', #{purchaseOrder.poNumber}, '%')</if>
<if test="purchaseOrder.productName != null and purchaseOrder.productName != ''"> and product_name like concat('%', #{purchaseOrder.productName}, '%')</if>
<if test="purchaseOrder.sku != null and purchaseOrder.sku != ''"> and sku like concat('%', #{purchaseOrder.sku}, '%')</if>
<if test="purchaseOrder.products != null and purchaseOrder.products != ''"> and products like concat('%', #{purchaseOrder.products}, '%')</if>
<if test="purchaseOrder.resellerId != null and purchaseOrder.resellerId != ''"> and reseller_id like concat('%', #{purchaseOrder.resellerId}, '%')</if>
<if test="purchaseOrder.orderStatus != null "> and order_status = #{purchaseOrder.orderStatus}</if>
<if test="purchaseOrder.beginOrderDate != null and purchaseOrder.beginOrderDate != '' and purchaseOrder.endOrderDate != null and purchaseOrder.endOrderDate != ''"> and order_date between #{purchaseOrder.beginOrderDate} and #{purchaseOrder.endOrderDate}</if>
<if test="purchaseOrder.num != null "> and num = #{purchaseOrder.num}</if>
<if test="purchaseOrder.tax != null "> and tax = #{purchaseOrder.tax}</if>
<if test="purchaseOrder.rate != null and purchaseOrder.rate != ''"> and rate = #{purchaseOrder.rate}</if>
<if test="purchaseOrder.unitPriceTaxBefore != null "> and unit_price_tax_before = #{purchaseOrder.unitPriceTaxBefore}</if>
<if test="purchaseOrder.unitPriceTaxAfter != null "> and unit_price_tax_after = #{purchaseOrder.unitPriceTaxAfter}</if>
<if test="purchaseOrder.sumPriceTaxBefore != null "> and sum_price_tax_before = #{purchaseOrder.sumPriceTaxBefore}</if>
<if test="purchaseOrder.sumPriceTaxAfter != null "> and sum_price_tax_after = #{purchaseOrder.sumPriceTaxAfter}</if>
<if test="purchaseOrder.isoCountryCode != null and purchaseOrder.isoCountryCode != ''"> and iso_country_code like concat('%', #{purchaseOrder.isoCountryCode}, '%')</if>
<if test="purchaseOrder.clientTransactionId != null and purchaseOrder.clientTransactionId != ''"> and client_transaction_id like concat('%', #{purchaseOrder.clientTransactionId}, '%')</if>
<if test="purchaseOrder.storeId != null and purchaseOrder.storeId != ''"> and store_id like concat('%', #{purchaseOrder.storeId}, '%')</if>
<if test="purchaseOrder.fulfillmentType != null "> and fulfillment_type = #{purchaseOrder.fulfillmentType}</if>
<if test="purchaseOrder.tokenPackage != null and purchaseOrder.tokenPackage != ''"> and token_package like concat('%', #{purchaseOrder.tokenPackage}, '%')</if>
<if test="purchaseOrder.isDeleted != null "> and is_deleted = #{purchaseOrder.isDeleted}</if>
<if test="purchaseOrder.cusName != null and purchaseOrder.cusName != ''"> and cus_name like concat('%', #{purchaseOrder.cusName}, '%')</if>
<if test="purchaseOrder.createMan != null and purchaseOrder.createMan != ''"> and create_man = #{purchaseOrder.createMan}</if>
<if test="purchaseOrder.updateMan != null and purchaseOrder.updateMan != ''"> and update_man = #{purchaseOrder.updateMan}</if>
<if test="purchaseOrder.beginOrderDate != null and purchaseOrder.endOrderDate != null"> and order_date between #{purchaseOrder.beginOrderDate} and #{purchaseOrder.endOrderDate}</if> // 订购时间 beginOrderDate endOrderDate
<if test="purchaseOrder.beginOrderTime != null and purchaseOrder.endOrderTime != null"> and order_time between #{purchaseOrder.beginOrderTime} and #{purchaseOrder.endOrderTime}</if> // 采购时间 beginOrderTime endOrderTime
<if test="purchaseOrder.beginDelTime != null and purchaseOrder.endDelTime != null"> and del_time between #{purchaseOrder.beginDelTime} and #{purchaseOrder.endDelTime}</if> // 交付时间 beginDelTime endDelTime
<if test="purchaseOrder.beginReturnTime != null and purchaseOrder.endReturnTime != null"> and return_time between #{purchaseOrder.beginReturnTime} and #{purchaseOrder.endReturnTime}</if> // 退货时间 beginReturnTime endReturnTime
<if test="purchaseOrder.orderMan != null and purchaseOrder.orderMan != ''"> and order_man = #{purchaseOrder.orderMan}</if>
<if test="purchaseOrder.delTime != null "> and del_time = #{purchaseOrder.delTime}</if>
<if test="purchaseOrder.delMan != null and purchaseOrder.delMan != ''"> and del_man = #{purchaseOrder.delMan}</if>
<if test="purchaseOrder.returnTime != null "> and return_time = #{purchaseOrder.returnTime}</if>
<if test="purchaseOrder.returnMan != null and purchaseOrder.returnMan != ''"> and return_man = #{purchaseOrder.returnMan}</if>
</where>
order by update_time desc
</select>
</mapper>
11.3 批量逻辑删除
public interface TokenMapper {
/**
* 批量删除Token状态
*
* @param tokenIds 需要删除的数据主键集合
* @return 结果
*/
int deleteTokenByTokenIds(Long[] tokenIds);
}
<mapper namespace="com.ekostar.microsoft.mapper.TokenMapper">
<delete id="deleteTokenByTokenIds" parameterType="String">
update ms_token set is_deleted=2 where token_id in
<foreach item="tokenId" collection="array" open="(" separator="," close=")">
#{tokenId}
</foreach>
</delete>
</mapper>
11.4 批量查看
public interface TokenMapper {
List<Token> selectTokenByIds(@Param("tokenIds") List<Long> tokenIds);
}
<mapper namespace="com.ekostar.microsoft.mapper.TokenMapper">
<select id="selectTokenByIds" resultMap="TokenResult">
<include refid="selectTokenVo"/>
where is_deleted = 1 and token_id in
<foreach collection="tokenIds" separator="," item="item" index="index" open="(" close=")">
#{item}
</foreach>
</select>
</mapper>
11.5 批量插入
<insert id="batchInsert" keyColumn="id" keyProperty="id" parameterType="map" useGeneratedKeys="true">
<!--@mbg.generated-->
insert into m_user
(username, `password`, email, gender, avatar, `status`, lasted, created, modified
)
values
<foreach collection="list" item="item" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.gender}, #{item.avatar},
#{item.status}, #{item.lasted}, #{item.created}, #{item.modified})
</foreach>
</insert>
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderSubmitVO implements Serializable {
//订单id
private Long id;
//订单号
private String orderNumber;
//订单金额
private BigDecimal orderAmount;
//下单时间
private LocalDateTime orderTime;
}
-------------------------------------------------------------------------------------------------------------
/**
* 用户下单
* @param ordersSubmitDTO
* @return
*/
@Transactional
public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
//1. 处理各种业务异常(地址簿为空、购物车数据为空)
AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
if(addressBook == null){
//抛出业务异常
throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
}
//检查用户的收货地址是否超出配送范围
//checkOutOfRange(addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());
//查询当前用户的购物车数据
Long userId = BaseContext.getCurrentId();
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setUserId(userId);
List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);
if(shoppingCartList == null || shoppingCartList.size() == 0){
//抛出业务异常
throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
}
//2. 向订单表插入1条数据
Orders orders = new Orders();
BeanUtils.copyProperties(ordersSubmitDTO, orders);
orders.setOrderTime(LocalDateTime.now());
orders.setPayStatus(Orders.UN_PAID);
orders.setStatus(Orders.PENDING_PAYMENT);
orders.setNumber(String.valueOf(System.currentTimeMillis()));
orders.setAddress(addressBook.getDetail());
orders.setPhone(addressBook.getPhone());
orders.setConsignee(addressBook.getConsignee());
orders.setUserId(userId);
orderMapper.insert(orders);
//3. 向订单明细表插入n条数据
List<OrderDetail> orderDetailList = new ArrayList<>();
for (ShoppingCart cart : shoppingCartList) {
OrderDetail orderDetail = new OrderDetail();//订单明细
BeanUtils.copyProperties(cart, orderDetail);
orderDetail.setOrderId(orders.getId());//设置当前订单明细关联的订单id
orderDetailList.add(orderDetail);
}
orderDetailMapper.insertBatch(orderDetailList);
//4. 清空当前用户的购物车数据
shoppingCartMapper.deleteByUserId(userId);
//5. 封装VO返回结果
OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
.id(orders.getId())
.orderTime(orders.getOrderTime())
.orderNumber(orders.getNumber())
.orderAmount(orders.getAmount())
.build();
return orderSubmitVO;
}
11.6 批量更新
public interface TokenMapper {
/**
* 批量修改
* @param tokenList
*/
void updateBatchToken(@Param("tokenList") List<Token> tokenList);
}
<mapper namespace="com.ekostar.microsoft.mapper.TokenMapper">
<update id="updateBatchToken">
update `ms_token`
<trim prefix="set" suffixOverrides=",">
<trim prefix="email_status = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.emailStatus != null">
when token_id=#{item.tokenId} then #{item.emailStatus}
</if>
</foreach>
</trim>
<trim prefix="return_fail_rea = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
when token_id=#{item.tokenId} then #{item.returnFailRea}
</foreach>
</trim>
<trim prefix="client_transaction_id = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.clientTransactionId != null">
when token_id=#{item.tokenId} then #{item.clientTransactionId}
</if>
</foreach>
</trim>
<trim prefix="redemption_date_time = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.redemptionDateTime != null">
when token_id=#{item.tokenId} then #{item.redemptionDateTime}
</if>
</foreach>
</trim>
<trim prefix="token_status = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.tokenStatus != null">
when token_id=#{item.tokenId} then #{item.tokenStatus}
</if>
</foreach>
</trim>
<trim prefix="last_updateof_status = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.lastUpdateofStatus != null">
when token_id=#{item.tokenId} then #{item.lastUpdateofStatus}
</if>
</foreach>
</trim>
<trim prefix="token_class_name = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.tokenClassName != null">
when token_id=#{item.tokenId} then #{item.tokenClassName}
</if>
</foreach>
</trim>
<trim prefix="promotion_name = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.promotionName != null">
when token_id=#{item.tokenId} then #{item.promotionName}
</if>
</foreach>
</trim>
<trim prefix="token_package = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.tokenPackage != null">
when token_id=#{item.tokenId} then #{item.tokenPackage}
</if>
</foreach>
</trim>
<trim prefix="token_package = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.tokenPackage != null">
when token_id=#{item.tokenId} then #{item.tokenPackage}
</if>
</foreach>
</trim>
<trim prefix="status = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.status != null">
when token_id=#{item.tokenId} then #{item.status}
</if>
</foreach>
</trim>
<trim prefix="order_time = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.orderTime != null">
when token_id=#{item.tokenId} then #{item.orderTime}
</if>
</foreach>
</trim>
<trim prefix="order_man = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.orderMan != null">
when token_id=#{item.tokenId} then #{item.orderMan}
</if>
</foreach>
</trim>
<trim prefix="del_time = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.delTime != null">
when token_id=#{item.tokenId} then #{item.delTime}
</if>
</foreach>
</trim>
<trim prefix="del_man = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.delMan != null">
when token_id=#{item.tokenId} then #{item.delMan}
</if>
</foreach>
</trim>
<trim prefix="return_time = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.returnTime != null">
when token_id=#{item.tokenId} then #{item.returnTime}
</if>
</foreach>
</trim>
<trim prefix="return_man = case" suffix="end,">
<foreach collection="tokenList" item="item" index="index">
<if test="item.returnMan != null">
when token_id=#{item.tokenId} then #{item.returnMan}
</if>
</foreach>
</trim>
</trim>
where token_id in
<foreach collection="tokenList" separator="," item="item" index="index" open="(" close=")">
#{item.tokenId}
</foreach>
</update>
</mapper>
11.7 批量删除
@Mapper
public interface UserMapper {
int deleteByIds(Long[] ids);
}
<mapper namespace="org.myslayers.mapper.UserMapper">
<delete id="deleteByIds" parameterType="String">
delete from m_user where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
11.8 清空表数据
public interface ProductCatalogMapper extends BaseMapper<ProductCatalog> {
/**
* 清空表数据
* @return
*/
int truncateTable();
}
<mapper namespace="com.ekostar.microsoft.mapper.ProductCatalogMapper">
<delete id="truncateTable">
TRUNCATE TABLE ms_product_catalog
</delete>
</mapper>