Authored by baoss

Merge branch 'develop-3540' into develop

... ... @@ -9,14 +9,19 @@
<i-spin v-if="loading"></i-spin>
<i-form v-else ref="formCoupon" :rules="ruleValidate" :model="formData" :label-width="80">
<i-form-item class="form-group" label="优惠券类型"></i-form-item>
<i-form-item label="用户类型" prop="userType">
<radio-group v-model="formData.userType" @on-change="changeUserType">
<radio :label="1" :disabled="!!formData.id">买家</radio>
<radio :label="2" :disabled="!!formData.id">卖家</radio>
</radio-group>
</i-form-item>
<div :key="formData.userType">
<i-form-item label="优惠券类型" prop="couponType">
<i-select style="width: 100px;" v-model="formData.couponType" :disabled="readonly">
<i-option :value="0">请选择</i-option>
<i-option :value="100">活动券</i-option>
<i-option :value="110">运费券</i-option>
<i-option v-for="item in counponOptions" :value="item.value" :key="item.value">{{ item.label }}</i-option>
</i-select>
</i-form-item>
<i-form-item class="form-group" label="基本信息"></i-form-item>
<i-form-item label="Token" v-if="couponToken">{{couponToken}}</i-form-item>
<i-form-item label="名称" prop="couponName">
... ... @@ -59,12 +64,16 @@
></i-date-picker>
</i-form-item>
<i-form-item label="优惠券说明" prop="remark">
<i-input
type="textarea"
placeholder="优惠券使用条件简介"
:disabled="allreadonly"
v-model="formData.remark"
></i-input>
<i-row>
<i-col span="20">
<i-input
type="textarea"
placeholder="优惠券使用条件简介"
:disabled="allreadonly"
v-model="formData.remark"
></i-input>
</i-col>
</i-row>
</i-form-item>
<i-form-item class="form-group" label="使用条件"></i-form-item>
<i-form-item label="优惠条件" prop="useLimitType" style="display: inline-block; width: 100%">
... ... @@ -93,23 +102,49 @@
</i-form-item>
<i-form-item label="适用范围" prop="productLimitType">
<i-select style="width: 100px;" v-model="formData.productLimitType" :disabled="readonly">
<i-option :value="1">指定商品</i-option>
<i-option :value="2">全部商品</i-option>
<i-option :value="3">排除商品</i-option>
</i-select>
<radio-group v-model="formData.productLimitType" @on-change="changeProductType">
<radio v-for = "(val, key) in allowproductLimitTypeList" :key="formData.userType+key" :label="+key" :disabled="readonly">{{val}}</radio>
</radio-group>
</i-form-item>
<div :key="formData.productLimitType">
<i-form-item prop="brandVal" v-if="formData.productLimitType === 4">
<Select v-model="formData.brandVal" multiple style="width:300px">
<Option v-for="item in brandList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select>
</i-form-item>
<i-form-item :prop="cascaderData.prop" v-else-if="formData.productLimitType === 5 || formData.productLimitType === 6">
<i-row v-for="item in cascaderData.formData.items" :key="item.index" class="add-item">
<i-col span="16">
<Cascader :data="cascaderData.data" v-model="item.value" :load-data="cascaderData.loadData"></Cascader>
</i-col>
<i-col span="4" offset="1" v-if="item.index > 1">
<i-button @click="handleRemove(cascaderData.formData, item.index)" type="error" size="small" ghost icon="md-close" shape="circle"></i-button>
</i-col>
</i-row>
<i-row>
<i-col span="10">
<i-button type="dashed" long @click="handleAdd(cascaderData.formData)" icon="md-add">添加项</i-button>
</i-col>
</i-row>
</i-form-item>
<i-form-item
prop="productLimitValue"
v-if="formData.productLimitType === 1 || formData.productLimitType === 3"
:prop="uploadProp"
:label="formData.productLimitType === 1 ? '' : '排除商品'"
>
<i-input
type="textarea"
:disabled="readonly"
placeholder="填写商品编码,多个商品编码用英文逗号分隔"
v-model="formData.productLimitValue"
></i-input>
<i-row>
<i-col span="20">
<i-input
type="textarea"
:key ="formData.productLimitType"
:disabled="readonly"
placeholder="填写商品编码,多个商品编码用英文逗号分隔"
v-model="formData[uploadProp]"
></i-input>
</i-col>
</i-row>
<i-poptip trigger="hover">
<div slot="content">
<p>1.上传文件必须是xlsx文件</p>
... ... @@ -125,6 +160,7 @@
</i-upload>
</i-poptip>
</i-form-item>
</div>
<!--<i-form-item label="禁用商品类型">
<checkbox-group v-model="formData.skupForbidTypeLable" @on-change="getCheckBox">
<checkbox label="现货" :disabled="readonly"></checkbox>
... ... @@ -136,25 +172,13 @@
</i-form-item>-->
<i-form-item label="可用商品类型">
<checkbox-group v-model="formData.skupAllowTypeLabel" @on-change="getCheckBox">
<!-- <checkbox label="线下店订单" :disabled="readonly"></checkbox>-->
<checkbox label="极速发货" :disabled="readonly"></checkbox>
<checkbox label="极速寄存" :disabled="readonly"></checkbox>
<checkbox label="预售" :disabled="readonly"></checkbox>
<checkbox label="瑕疵" :disabled="readonly"></checkbox>
<checkbox label="二手" :disabled="readonly"></checkbox>
<!-- <checkbox label="鉴定" :disabled="readonly"></checkbox>-->
<checkbox label="海外直邮" :disabled="readonly"></checkbox>
<checkbox label="现货发货" :disabled="readonly"></checkbox>
<checkbox label="现货寄存" :disabled="readonly"></checkbox>
<checkbox label="闪购发货" :disabled="readonly"></checkbox>
<checkbox label="闪购寄存" :disabled="readonly"></checkbox>
<checkbox v-for = "(val, key) in allowTypeLabelList" :key="formData.userType+key" :label="key" :disabled="readonly">{{val}}</checkbox>
</checkbox-group>
</i-form-item>
<i-form-item label="购买渠道" prop="useLimitType">
<i-form-item label="购买渠道" prop="businessClientLabel">
<checkbox-group v-model="formData.businessClientLabel" @on-change="getChannelCheckBox">
<checkbox label="UFO" :disabled="readonly"></checkbox>
<checkbox label="闲鱼" :disabled="readonly"></checkbox>
<checkbox v-for = "(val, key) in businessClientLabelMap" :key="key" :label="key" :disabled="readonly">{{val}}</checkbox>
</checkbox-group>
</i-form-item>
<i-form-item label="需要校验" prop="checkRequired">
... ... @@ -163,6 +187,7 @@
<i-form-item label="展示在详情页" prop="isShowInDetail">
<checkbox v-model="formData.isShowInDetail" :disabled="allreadonly" @on-change="setIsShowInDetail"></checkbox>
</i-form-item>
</div>
</i-form>
</i-modal>
</template>
... ... @@ -187,21 +212,36 @@ const forbidenLabelMap = {
5: "全新瑕疵",
3: "闪购"
};
const userCouponType = {
buyer: [{
value: 100,
label: '活动券'
},
{
value: 110,
label: '运费券'
}],
seller: [{
value: 100,
label: '活动券'
}]
}
const allowTypeMap = {
// '线下店订单': '2',
极速发货: "9-N",
极速寄存: "9-Y",
预售: "4",
瑕疵: "5",
二手: "6",
// '鉴定': '8',
海外直邮: "17",
现货发货: "1-N",
现货寄存: "1-Y",
闪购发货: "3-N",
闪购寄存: "3-Y"
const sellerAllowLabel = {
"1-N": "现货发货",
"4": "预售",
"5": "瑕疵",
"6": "二手",
};
const allowproductLimitTypeList = {
1: "指定商品",
2: "全部商品",
// 3: "排除商品",
4: "特定品牌",
5: "特定品类",
6: "特定系列"
}
const allowLabelMap = {
// '2': '线下店订单',
"9-N": "极速发货",
... ... @@ -216,51 +256,88 @@ const allowLabelMap = {
"3-N": "闪购发货",
"3-Y": "闪购寄存"
};
const businessClientTypeMap = {
UFO: "ufo",
闲鱼: "h5/xianyu"
};
const businessClientLabelMap = {
ufo: "UFO",
"h5/xianyu": "闲鱼"
};
export default {
components: {},
name: "ModalCreateCoupon",
data() {
return {
readonly: false,
allreadonly: false,
visiable: false,
loading: false,
posting: true,
uploadTxt: "",
couponToken: "",
formData: {
const initFormData = {
id: 0,
couponName: "",
couponType: 0,
couponNum: 0,
couponType: 0,
useNum: 1,
couponAmount: 0,
useLimitType: 0,
remark: "",
productLimitType: 2,
productLimitValue: "",
productLimitType: 2,
brandVal: [],
category: {
index: 1,
items: [{
index: 1,
value: []
}]
},
series: {
index: 1,
items: [{
index: 1,
value: []
}]
},
excludeProductIds: "",
useLimitValue: 0,
time: ["", ""],
receiveTime: ["", ""],
// skupForbidTypeLable:[],
// skupForbidType: ''
skupAllowTypeLabel: [],
skupAllowType: "",
businessClient: "",
businessClientLabel: [],
checkRequired: 0,
isCheckRequired: true,
isCheckRequired: false,
// 是否展示在详情页
isShowInDetail: false
isShowInDetail: false,
// skupForbidTypeLable:[],
// skupForbidType: ''
};
export default {
components: {},
name: "ModalCreateCoupon",
data() {
return {
readonly: false,
allreadonly: false,
visiable: false,
loading: false,
posting: true,
uploadTxt: "",
couponToken: "",
formData: {
userType: 1,
...initFormData
},
buyerFormDataCache: {
userType: 1,
...initFormData
},
sellerFormDataCache: {
userType: 2,
...initFormData
},
lastSelectType: 2,
excludeValCache: {
2: "",
3: "",
4: "",
5: "",
6: ""
},
allowproductLimitTypeList,
businessClientLabelMap,
brandList: [],
categoryList: [],
seriesList: [],
ruleValidate: {
couponType: {
required: true,
... ... @@ -334,7 +411,7 @@ export default {
}
},
productLimitValue: {
required: false,
required: true,
validator: (rule, value, callback) => {
const ids = (value || "").split(",");
... ... @@ -347,19 +424,97 @@ export default {
}
}
},
excludeProductIds: {
required: false,
validator: (rule, value, callback) => {
const ids = (value || "").split(",");
if (ids.some(id => (id ? !parseInt(id) : false))) {
callback(new Error("适用范围格式错误"));
} else {
callback();
}
}
},
brandVal: {
required: true,
validator: (rule, value, callback) => {
if (value.length > 0) {
callback();
} else {
callback(new Error("请选择品牌"));
}
}
},
category: {
required: true,
validator: (rule, value, callback) => {
if(value.items.length >0 && value.items[0].value.length > 0) { //保证至少有一组值
callback();
} else {
callback(new Error("请选择品类"));
}
}
},
series: {
required: true,
validator: (rule, value, callback) => {
if(value.items.length >0 && value.items[0].value.length > 0) { //保证至少有一组值
callback();
} else {
callback(new Error("请选择系列"));
}
}
},
productLimitType: {
required: true,
validator: (rule, value, callback) => {
if (value === 1 || value === 2 || value === 3) {
if (value > 0) {
callback();
} else {
callback(new Error("请选择类型"));
}
}
},
businessClientLabel: {
required: true,
validator: (rule, value, callback) => {
if (value.length > 0) {
callback();
} else {
callback(new Error("请选择购买渠道"));
}
}
}
}
};
},
computed: {
allowTypeLabelList: function() {
return this.formData.userType === 1 ? allowLabelMap : sellerAllowLabel
},
counponOptions: function() {
return this.formData.userType === 1 ? userCouponType.buyer : userCouponType.seller
},
uploadProp: function() {
return this.formData.productLimitType === 1 ? 'productLimitValue' : 'excludeProductIds'
},
cascaderData: function() {
let cascaderObj = {}
if (this.formData.productLimitType === 5) {
cascaderObj.prop = "category"
cascaderObj.formData = this.formData.category
cascaderObj.data = this.categoryList
cascaderObj.loadData = this.loadCategoryData
}else if(this.formData.productLimitType === 6) {
cascaderObj.prop = "series"
cascaderObj.formData = this.formData.series
cascaderObj.data = this.seriesList
cascaderObj.loadData = this.loadSeriesData
}
return cascaderObj
}
},
methods: {
async show(id, readonly, allreadonly) {
// console.log(id)
... ... @@ -367,30 +522,12 @@ export default {
this.allreadonly = allreadonly;
this.posting = this.visiable = true;
this.$refs.formCoupon.resetFields();
for (let key in this.excludeValCache) {
this.excludeValCache[key] = ""
}
this.couponToken = "";
let initData = {
id: 0,
couponName: "",
couponNum: 0,
couponType: 0,
useNum: 1,
couponAmount: 0,
useLimitType: 0,
remark: "",
productLimitValue: "",
productLimitType: 2,
useLimitValue: 0,
time: ["", ""],
skupAllowTypeLabel: [],
skupAllowType: "",
businessClientLabel: [],
businessClient: "",
checkRequired: 0,
isShowInDetail: false
// skupForbidTypeLable:[],
// skupForbidType: ''
};
let initData = initFormData
initData.userType = 1
if (id) {
this.loading = true;
const result = await api._get("/ufoPlatform/coupon/getCouponInfo", {
... ... @@ -403,28 +540,16 @@ export default {
if (result.code === 200) {
const coupon = result.data.coupon;
console.log(result.data)
const productLimits = result.data.productLimits;
this.couponToken = coupon.couponToken;
let skupAllowTypeLabel = [];
if (coupon.skupAllowType) {
let arr = coupon.skupAllowType.split(",");
for (let i = 0; i < arr.length; i++) {
skupAllowTypeLabel.push(allowLabelMap[arr[i]]);
}
}
let businessClientTypeLabel = [];
if (coupon.businessClient) {
let arr = coupon.businessClient.split(",");
for (let i = 0; i < arr.length; i++) {
businessClientTypeLabel.push(businessClientLabelMap[arr[i]]);
}
}
let isCheckRequired = coupon.checkRequired === 1
console.log('=====:'+isCheckRequired)
initData = {
...initFormData,
id,
userType: coupon.userType,
couponName: coupon.couponName,
couponNum: coupon.couponNum,
couponType: coupon.couponType || 0,
... ... @@ -433,9 +558,7 @@ export default {
useLimitType: coupon.useLimitType,
remark: coupon.remark,
productLimitType: coupon.productLimitType,
productLimitValue: (productLimits || [])
.map(i => i.productId)
.join(","),
excludeProductIds: result.data.excludeProductIds,
useLimitValue: coupon.useLimitValue,
time: [
dayjs.unix(coupon.startTime).format("YYYY-MM-DD HH:mm:ss"),
... ... @@ -445,20 +568,127 @@ export default {
dayjs.unix(coupon.receiveStartTime).format("YYYY-MM-DD HH:mm:ss"),
dayjs.unix(coupon.receiveEndTime).format("YYYY-MM-DD HH:mm:ss")
],
skupAllowTypeLabel: skupAllowTypeLabel,
skupAllowType: coupon.skupAllowType,
businessClientLabel: businessClientTypeLabel,
businessClient: coupon.businessClient, //购买渠道
skupAllowTypeLabel: coupon.skupAllowType.split(","),
businessClientLabel: coupon.businessClient.split(","), //购买渠道
checkRequired: coupon.checkRequired,
isCheckRequired,
isShowInDetail: result.data.showInPrdDetail === 'Y'
};
this.setSelectItems(coupon.productLimitType,coupon.productLimitValue)
} else {
result.message && this.$Message.warning(result.message);
}
}
this.formData = initData;
},
async setSelectItems(type,val) {
await this.getSelectItems(type)
this.setValToSelect(type,val)
this.lastSelectType = type
},
setValToSelect(type,val) {
switch (type) {
case 1:
this.formData.productLimitValue = val
break
case 4:
this.formData.brandVal = val.split(",").map(item => parseInt(item))
break
case 5:
this.formData.category = this.getFormSelectedVal(val)
break
case 6:
this.formData.series = this.getFormSelectedVal(val)
}
},
getFormSelectedVal(val) {
let selectedVal = {}
let valArr = val.split(",")
selectedVal.index = valArr.length
let itemsArr = []
for(let i = 0; i < valArr.length; i++) {
let item = {}
item.index = i+1
item.value = valArr[i].split("-").map(item => parseInt(item))
itemsArr.push(item)
}
selectedVal.items = itemsArr
return selectedVal
},
async getSelectItems(type) {
let typeData = {
4: { url: "/ufoPlatform/brand/getBrandName",name: "brandList"},
5: { url: "/ufoPlatform/productSort/getLevel1SortIdAndName", name: "categoryList"},
6: { url: "/ufoPlatform/brand/getBrandName", name: "seriesList"}
};
if(!typeData[type]) {
return
}
let dataListName = typeData[type].name
if(this[dataListName].length > 0) {
return this[dataListName]
}
const result = await api._get(typeData[type].url)
let dataList = result.data
dataList.map((item) => {
item.label = item.text
item.value = item.id
delete item.text
delete item.id
if(+type === 6 || +type == 5) {
item.children = []
item.loading = false
}
return item
})
this[dataListName] = dataList
},
loadSeriesData (item, callback) {
this.loadData("seires", item, callback)
},
loadCategoryData (item, callback) {
this.loadData("category", item, callback)
},
async loadData (name, item, callback) {
let loadRequest = {
"seires": {url: "/ufoPlatform/brandSeries/querySeriesByBrandId", params: {brandId: item.value}},
"category": {url: "/ufoPlatform/productSort/getLevel2SortBySortId", params: {sortId: item.value}}
}
item.loading = true;
const result = await api._get(loadRequest[name].url, loadRequest[name].params)
let childrenList = result.data
childrenList.map((item) => {
item.label = item.text
item.value = item.id
delete item.text
delete item.id
return item
})
item.children = childrenList
item.loading = false;
callback();
},
handleAdd (cascaderData) {
cascaderData.index++;
cascaderData.items.push({index: cascaderData.index,value:[]});
},
handleRemove (cascaderData, index) {
let totalItem = cascaderData.index
cascaderData.index--;
if(index < totalItem) { // 删除中间项时 后面index重置
cascaderData.items.splice(index-1,1);
let newData = cascaderData.items
for(let i = index-1; i < cascaderData.index; i++) {
newData[i].index--
}
cascaderData.items = newData
} else {
cascaderData.items.pop();
}
},
onOk() {
this.$refs.formCoupon.validate(valid => {
if (!valid) {
... ... @@ -483,30 +713,51 @@ export default {
setIsShowInDetail(checked) {
this.formData.isShowInDetail = checked
},
getCheckBox() {
// checkbox勾选取消的监测
let arr = [];
for (let i = 0; i < this.formData.skupAllowTypeLabel.length; i++) {
let allowType = this.formData.skupAllowTypeLabel[i];
// console.log(allowType);
arr.push(allowTypeMap[allowType]);
changeUserType(val) {
if(val === 2) {
this.buyerFormDataCache = {...this.formData, userType: 1}
this.formData = this.sellerFormDataCache
} else {
this.sellerFormDataCache = {...this.formData, userType: 2}
this.formData = this.buyerFormDataCache
}
},
// console.log(arr);
this.formData.skupAllowType = arr.join(",");
changeProductType(val) {
// 排除商品缓存设置
this.excludeValCache[this.lastSelectType] = this.formData.excludeProductIds
this.formData.excludeProductIds = this.excludeValCache[val]
this.lastSelectType = val
this.getSelectItems(val)
},
getChannelCheckBox() {
let arr = [];
for (let i = 0; i < this.formData.businessClientLabel.length; i++) {
let businessClientType = this.formData.businessClientLabel[i];
// console.log(businessClientType);
arr.push(businessClientTypeMap[businessClientType]);
}
// console.log(arr);
this.formData.businessClient = arr.join(",");
getLimitVal(propName) {
let processData = this.formData[propName].items
let idsArr = []
for(let i = 0; i < processData.length; i++) {
if(processData[i].value.length > 0) {
let lastId = processData[i].value.pop()
idsArr.push(lastId)
}
}
return idsArr.join(",")
},
processProductLimitValue(type) {
let valueType = {
1: this.formData.productLimitValue,
2: "",
3: "",
4: this.formData.brandVal.join(","),
5: this.getLimitVal('category'),
6: this.getLimitVal('series')
}
return valueType[type]
},
async saveData(params) {
console.log('post params')
console.log(params)
let that = this
if (this.allreadonly) {
this.visiable = false;
return;
... ... @@ -514,6 +765,7 @@ export default {
const result = await api._post("/ufoPlatform/coupon/saveOrUpdateCoupon", {
id: params.id || void 0,
userType: params.userType,
couponName: params.couponName,
couponAmount: params.couponAmount,
couponNum: params.couponNum,
... ... @@ -521,14 +773,15 @@ export default {
useNum: params.useNum,
useLimitValue: params.useLimitValue,
productLimitType: params.productLimitType,
productLimitValue: params.productLimitValue,
productLimitValue: this.processProductLimitValue(params.productLimitType),
excludeProductIds: params.excludeProductIds,
remark: params.remark,
useLimitType:
parseInt(params.useLimitType) >= 0 ? params.useLimitType : void 0,
startTime: params.time[0] ? dayjs(params.time[0]).unix() : void 0,
endTime: params.time[1] ? dayjs(params.time[1]).unix() : void 0,
skupAllowType: params.skupAllowType,
businessClient: params.businessClient,
skupAllowType: params.skupAllowTypeLabel.join(","),
businessClient: params.businessClientLabel.join(","),
receiveStartTime: params.receiveTime[0]
? dayjs(params.receiveTime[0]).unix()
: void 0,
... ... @@ -589,7 +842,8 @@ export default {
const worksheet = workbook.Sheets[firstSheetName];
const results = XLSX.utils.sheet_to_json(worksheet);
this.formData.productLimitValue = results
this.formData[this.uploadProp] = results
.map(r => r["商品编码"])
.filter(r => r)
.join(",");
... ... @@ -625,4 +879,7 @@ export default {
height: 30px;
background-color: #f5f7f9;
}
.add-item {
margin-bottom: 10px;
}
</style>
... ...
... ... @@ -19,6 +19,12 @@
<i-form-item prop="time">
<i-date-picker type="datetimerange" v-model="filter.time" placeholder="开始-结束时间" format="yyyy-MM-dd HH:mm" style="width: 250px"></i-date-picker>
</i-form-item>
<i-form-item prop="userType">
<i-select placeholder="选择用户类型" v-model="filter.userType" style="width: 160px;">
<i-option :value="1">买家</i-option>
<i-option :value="2">卖家</i-option>
</i-select>
</i-form-item>
</i-form>
</LayoutFilter>
<LayoutTools>
... ... @@ -57,7 +63,8 @@ export default {
id: '',
name: '',
status: '',
time: ['', '']
time: ['', ''],
userType: ''
},
page: 1,
total: 0,
... ... @@ -66,6 +73,11 @@ export default {
title: 'ID',
key: 'id',
width: 80
},
{
title: '用户类型',
key: 'userType',
width: 180
}, {
title: '券名称',
key: 'name',
... ... @@ -127,12 +139,13 @@ export default {
},
created() {
this.$nextTick(() => {
const {page, id, name, status, startTime, endTime} = qs.parse(location.search ? location.search.slice(1) : '');
const {page, id, name, status, startTime, endTime, userType} = qs.parse(location.search ? location.search.slice(1) : '');
this.filter.id = id || this.filter.id;
this.filter.name = name ? decodeURIComponent(name) : this.filter.name;
this.filter.status = status ? parseInt(status) : this.filter.status;
this.filter.time = (startTime && endTime) ? [dayjs(startTime), dayjs(endTime)] : this.filter.time;
this.filter.userType = userType || this.filter.userType
this.page = page ? parseInt(page) : 1;
this.fetchData(this.filter, this.page);
... ... @@ -207,10 +220,12 @@ export default {
const result = await api._get('/ufoPlatform/coupon/queryCoupons', Object.assign({
page,
}, this.getParams(params)));
console.log(this.getParams(params), result)
if (result.code === 200) {
this.total = result.data.total;
this.data = result.data.coupons;
let coupons = result.data.coupons;
coupons.map(item => item.userType = (item.userType === 1 ? "买家" : "卖家"))
this.data = coupons;
this.$Loading.finish();
} else {
result.message && this.$Message.warning(result.message);
... ... @@ -229,7 +244,8 @@ export default {
status,
startTime,
endTime,
curTime
curTime,
userType:params.userType
};
}
},
... ...