You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
489 lines
15 KiB
489 lines
15 KiB
<template> |
|
<view class="page"> |
|
<template v-for="c in courses"> |
|
<view v-if="c.list.length && c.list.filter(e => !e.edited).length" class="block"> |
|
<view class="type-wrap"> |
|
<view class="l-title">{{ c.name }}</view> |
|
<view class="batch"> |
|
<input class="deadline" type="number" v-model="c.deadline" placeholder="批量输入" @change="batchDeadlineChange(c)"> |
|
<view class="unit" @click="batchUnitChange(c)">{{ units.find(e => e.id === c.unit).text }}</view> |
|
</view> |
|
<uni-icons class="arrow" type="top" size="20" color="#007EFF" @click="toggle(c)"></uni-icons> |
|
</view> |
|
|
|
<view v-show="!c.shrink"> |
|
<template v-for="(item, i) in c.list"> |
|
<view v-if="!item.edited" :key="i"> |
|
<view class="pro-name"> |
|
<view class="left"> |
|
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image> |
|
{{ item.productName }} |
|
</view> |
|
<uni-icons class="del" type="trash" size="25" color="#ADADAD" @click="delCourse(c, i)"></uni-icons> |
|
</view> |
|
<view class="form-list"> |
|
<view class="line"> |
|
<view class="name">产品类型</view> |
|
<view class="val">{{ item.typeName }}</view> |
|
</view> |
|
<view :class="['line req', {err: err === 'periodOfUse' + item.dataOrCourseId + item.authority}]"> |
|
<view class="name">使用期限</view> |
|
<input class="period" type="number" v-model="item.periodOfUse" placeholder="请输入" @input="dateChange(item, !item.authority)" @change="handleErr(item, 'periodOfUse')"> |
|
<view class="val unit" @click="selectUnit(item)"> |
|
<text>{{ units.find(e => e.id === item.options).text }}</text> |
|
<image class="icon" src="@/static/image/arrow-down.png" mode="widthFix"></image> |
|
</view> |
|
</view> |
|
<view :class="['line req', {err: err === 'startTime' + item.dataOrCourseId + item.authority}]"> |
|
<view class="name">起止日期</view> |
|
<uni-datetime-picker type="date" v-model="item.startTime" :border="false" @change="dateChange(item)"> |
|
<view :class="['ph', {val: item.startTime}]"> |
|
{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}} |
|
</view> |
|
</uni-datetime-picker> |
|
</view> |
|
<view :class="['line req', {err: err === 'accountNum' + item.dataOrCourseId + item.authority}]"> |
|
<view class="name">数量</view> |
|
<view v-if="item.authority" class="val">1</view> |
|
<input v-else type="number" v-model="item.accountNum" placeholder="请输入账号数量" @input="calcFinalPrice(item)" @change="handleErr(item, 'accountNum')"> |
|
</view> |
|
<view class="line"> |
|
<view class="name">{{ item.authority ? '市场价' : '市场单价' }}</view> |
|
<view class="val">{{ item.marketValue }}元</view> |
|
</view> |
|
<view class="line"> |
|
<view class="name">结算价</view> |
|
<view class="val">{{ item.settlementPrice && item.settlementPrice + '元' }}</view> |
|
</view> |
|
<view class="line"> |
|
<view class="name">折扣率</view> |
|
<view class="val">{{ item.discountRate }}</view> |
|
</view> |
|
<view class="line"> |
|
<view class="name">市场服务费</view> |
|
<view class="val">{{ item.serviceFee }}元</view> |
|
</view> |
|
<view :class="['line req', {err: err === 'finalPrice' + item.dataOrCourseId + item.authority}]"> |
|
<view class="name">成交价</view> |
|
<view class="inline"> |
|
<input type="number" v-model="item.finalPrice" placeholder="请输入" @input="calcFinalValue(item)" @change="handleErr(item, 'finalPrice')"> |
|
元 |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
</template> |
|
</view> |
|
</view> |
|
</template> |
|
<view class="btn-wrap"> |
|
<view class="btn" @click="submit">确定</view> |
|
</view> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
import { getOrderOtherTime, queryCitySettlementPrice, renew } from '@/apis/modules/order.js' |
|
import { getPartnerTeamRates } from '@/apis/modules/parner.js' |
|
import { productCategoryList } from '@/apis/modules/product.js' |
|
export default { |
|
data() { |
|
return { |
|
orderType: 1, |
|
customerId: '', |
|
action: '', |
|
provinceId: '', |
|
cityId: '', |
|
timer: null, |
|
units: [{ |
|
text: '日', |
|
id: 0 |
|
}, { |
|
text: '月', |
|
id: 1 |
|
}, { |
|
text: '年', |
|
id: 2 |
|
}], |
|
unitText: ['日', '月', '年'], |
|
courses: {} , // 上一页缓存的产品 |
|
orderRepeat: [], |
|
repeatMsg: '', |
|
err: '', |
|
rate: '', |
|
submiting: false, |
|
} |
|
}, |
|
onShow() { |
|
const pages = getCurrentPages() |
|
const { options } = pages[pages.length - 1] |
|
this.orderType = options.orderType |
|
this.customerId = options.customerId |
|
this.action = options.action |
|
this.provinceId = options.provinceId |
|
this.cityId = options.cityId |
|
this.handleProduct() |
|
this.getRate() |
|
}, |
|
methods: { |
|
// 转换产品列表 |
|
async handleProduct() { |
|
const list = uni.getStorageSync('courses') |
|
let courses = {} |
|
|
|
// 产品分类 |
|
productCategoryList().then(res => { |
|
res.classificationList.forEach(e => { |
|
courses['list' + this.$util.getOrderType(e.classificationId)] = { |
|
shrink: false, |
|
name: e.classificationName, |
|
deadline: '', |
|
unit: 2, |
|
list: [] |
|
} |
|
}) |
|
const { provinceId, cityId } = this |
|
const isTrial = this.orderType == 2 |
|
list.map(async e => { |
|
// 查询产品管理设置的平台结算价 |
|
if (provinceId) { |
|
const res = await queryCitySettlementPrice(e.mallId, provinceId, cityId) |
|
if (res.mallPrice) e.settlementPriceUnit = res.mallPrice.discountRate || 0 |
|
} |
|
// 查询该产品的到期时间 |
|
const res = await renew({ |
|
authority: e.authority, |
|
customerId: this.customerId, |
|
productId: [e.mallId] |
|
}) |
|
|
|
const item = res.orderOthers |
|
if (item && item.length) { |
|
let date = new Date(item[0].endTime) |
|
date = new Date(date.setDate(date.getDate() + 1)) |
|
e.startTime = this.$util.formatDate(date, 'yyyy-MM-dd') |
|
} |
|
// 试用默认赋值1月后,需要计算结束日期 |
|
if (isTrial) { |
|
this.calcDate(e, !e.authority) |
|
} |
|
courses['list' + e.authority].list.push(e) |
|
}) |
|
this.courses = courses |
|
}).catch(e => {}) |
|
}, |
|
// 批量设置产品时间 |
|
batchDeadlineChange (c) { |
|
c.list.map(e => { |
|
e.periodOfUse = c.deadline |
|
this.calcDate(e, !e.authority) |
|
}) |
|
}, |
|
// 批量设置产品期限单位 |
|
batchUnitChange(c) { |
|
const that = this |
|
uni.showActionSheet({ |
|
title: '标题', |
|
itemList: that.unitText, |
|
success: ({ tapIndex }) => { |
|
c.unit = tapIndex |
|
c.list.map(e => { |
|
e.options = tapIndex |
|
that.calcDate(e, !e.authority) |
|
}) |
|
} |
|
}) |
|
}, |
|
// 单个产品选择年月日 |
|
selectUnit(item) { |
|
const that = this |
|
uni.showActionSheet({ |
|
title: '标题', |
|
itemList: that.unitText, |
|
success: ({ tapIndex }) => { |
|
item.options = tapIndex |
|
that.calcDate(item) |
|
} |
|
}) |
|
}, |
|
showUnit(i) { |
|
this.$refs.unit[i].show() |
|
}, |
|
// 收缩产品 |
|
toggle(c) { |
|
c.shrink = !c.shrink |
|
}, |
|
// 删除课程 |
|
delCourse(c, i) { |
|
uni.showModal({ |
|
title: '提示', |
|
content: '确定要删除吗?', |
|
success(res) { |
|
res.confirm && c.list.splice(i, 1) |
|
} |
|
}) |
|
}, |
|
// 使用期限输入回调 |
|
dateChange(row, fromData) { |
|
clearTimeout(this.timer) |
|
this.timer = setTimeout(() => { |
|
this.calcDate(row, fromData) |
|
}, 500) |
|
}, |
|
// 使用期限转换以及计算剩余天数 |
|
calcDate(row, fromData) { |
|
const { periodOfUse, options } = row |
|
let optionsData = 0 |
|
if (periodOfUse) { |
|
if (options == 1){ |
|
optionsData = periodOfUse === '12' ? 31536000000 : periodOfUse*30*24*60*60*1000 |
|
} else if (options == 2){ |
|
optionsData = periodOfUse*365*24*60*60*1000 |
|
} else { |
|
optionsData = periodOfUse*24*60*60*1000 |
|
} |
|
} |
|
let time = new Date(row.startTime).getTime() |
|
let endTime = time + optionsData |
|
let dt = new Date(endTime) |
|
row.endTime = (dt.getFullYear()) + "-" + (dt.getMonth() + 1) + "-" + (dt.getDate()) |
|
let endYear = endTime - time |
|
let endYears = endYear/1000/60/60/24 |
|
row.remainingPeriod = endYears |
|
const unit = row.options // 使用期限单位 |
|
const useUnit = row.periodOfUse // 使用期限 |
|
// 计算市场价 |
|
const price = row.marketPrice // 市场单价 |
|
// 结算单价是元/年,所以如果选择的不是年,要进行换算(日:/365,月:/12) |
|
row.marketValue = (!unit ? |
|
price / 365 * useUnit : |
|
unit === 1 ? |
|
price / 12 * useUnit : |
|
price * useUnit).toFixed(2) |
|
this.dealSettlePrice(row) |
|
// 只有改变了起止日期才需要调接口查询订单,该接口作用是把开始时间传过去,会返回一个提示或者时间,如果是时间,则把时间+1天,如果是提示,则无法保存 |
|
if (!fromData) { |
|
const cId = row.dataOrCourseId |
|
const date = new Date(row.startTime) |
|
const orderRepeat = this.orderRepeat |
|
getOrderOtherTime({ |
|
authority: row.authority, |
|
customerId: this.customerId, |
|
id: cId, |
|
startTime: this.$util.formatDate(date, 'yyyy-MM-dd'), |
|
endTime: row.endTime |
|
}).then(res => { |
|
orderRepeat.includes(cId) && orderRepeat.splice(orderRepeat.findIndex(e => e == cId), 1) |
|
if (res.endTime) { |
|
let time = new Date(res.endTime) |
|
time = new Date(time.setDate(time.getDate() + 1)) |
|
row.startTime = this.$util.formatDate(time, 'yyyy-MM-dd') |
|
} |
|
}).catch(res => { |
|
this.repeatMsg = res.message |
|
orderRepeat.includes(cId) || orderRepeat.push(cId) |
|
}) |
|
} |
|
// 折扣率 |
|
this.calcDiscount(row) |
|
}, |
|
// 计算结算价及平台服务费 |
|
dealSettlePrice(row) { |
|
// 如果是试用或者没选择,结算价和平台服务费都是0 |
|
if (this.orderType != 1) { |
|
row.settlementPrice = 0 |
|
row.serviceFee = 0 |
|
} else { |
|
const unit = row.options // 使用期限单位 |
|
const useUnit = row.periodOfUse // 使用期限 |
|
let sPrice = '' |
|
// 结算单价。计算规则:结算单价(**元/年)*购买时长(单位年)*数量(课程为1,数据为账号数量) |
|
const priceUnit = row.settlementPriceUnit |
|
sPrice = ((!unit ? |
|
priceUnit / 365 * useUnit : |
|
unit === 1 ? |
|
priceUnit / 12 * useUnit : |
|
priceUnit * useUnit) * (row.authority ? |
|
1 : |
|
row.accountNum)).toFixed((2)) |
|
row.settlementPrice = this.$util.handleNaN(sPrice) |
|
// 平台服务费 |
|
if (row.settlementPrice) { |
|
row.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2) |
|
} |
|
} |
|
}, |
|
// 查询合伙人团队费率 |
|
getRate() { |
|
getPartnerTeamRates({ |
|
teamId: uni.getStorageSync('team').teamId |
|
}).then(({ teamRates }) => { |
|
this.rate = teamRates.annualMarketingFee || 0 |
|
}).catch(res => {}) |
|
}, |
|
// 计算折扣率 |
|
calcDiscount(row) { |
|
const price = row.authority ? row.finalPrice : row.finalValue |
|
const { marketValue } = row |
|
// (原价-现价)÷原价 x100% |
|
if (price) row.discountRate = marketValue != 0 ? ((marketValue - price) / marketValue * 100).toFixed(2) + '%' : '0%' |
|
}, |
|
// 成交价修改后,计算成交单价,数据才需要 计算规则:成交价/账号数/时间(成交单价为元/账号/年,所以时间要换算成年的单位去计算) |
|
calcFinalValue(row) { |
|
clearTimeout(this.timer) |
|
this.timer = setTimeout(() => { |
|
const { authority, periodOfUse, options, accountNum, finalPrice } = row |
|
if (!authority && periodOfUse && accountNum && finalPrice) { |
|
row.finalValue = (finalPrice / accountNum / periodOfUse).toFixed(2) |
|
} |
|
// 折扣率 |
|
this.calcDiscount(row) |
|
//市场服务费 |
|
this.dealSettlePrice(row) |
|
}, 500) |
|
}, |
|
// 计算成交价。计算规则:成交单价*账号数*时间(成交单价为元/账号/年,所以时间要换算成年的单位去计算) |
|
calcFinalPrice(row) { |
|
clearTimeout(this.timer) |
|
this.timer = setTimeout(() => { |
|
const { finalValue, accountNum, periodOfUse, finalPrice } = row |
|
if (periodOfUse) { |
|
if (accountNum) { |
|
// 有成交单价,则成交价=成交单价*账号数*时间 |
|
if (finalValue) { |
|
row.finalPrice = Math.round(finalValue * periodOfUse * accountNum) |
|
} else if (!finalValue && finalPrice) { |
|
// 有成交价,没有成交单价,则成交单价=成交价/账号数/时间 |
|
row.finalValue = (finalPrice / periodOfUse / accountNum).toFixed(2) |
|
this.calcDiscount(row) |
|
} |
|
} else if (finalValue && finalPrice && !row.authority) { |
|
// 有成交价、成交单价,没有数量,则数量=成交价/时间/成交单价 |
|
row.accountNum = Math.floor(finalPrice / periodOfUse / finalValue) |
|
} |
|
} |
|
this.dealSettlePrice(row) |
|
}, 500) |
|
}, |
|
// 处理错误提示 |
|
handleErr(e, val) { |
|
if (val + e.dataOrCourseId + e.authority === this.err) this.err = '' |
|
}, |
|
// 确定 |
|
submit() { |
|
if (this.submiting) return false |
|
const { courses } = this |
|
const list = [] |
|
let msg = '' |
|
// 全部产品push到一个数组,方便校验 |
|
for (const i in courses) { |
|
list.push(...courses[i].list) |
|
} |
|
// 必填校验 |
|
for (const i in list) { |
|
const e = list[i] |
|
const suf = e.dataOrCourseId + '' + e.authority |
|
if (e.periodOfUse === '') { |
|
this.err = 'periodOfUse' + suf |
|
msg = '请输入使用期限!' |
|
break |
|
} |
|
if (!e.startTime) { |
|
this.err = 'startTime' + suf |
|
msg = '请选择起止日期!' |
|
break |
|
} |
|
if (e.accountNum === '') { |
|
this.err = 'accountNum' + suf |
|
msg = '请输入数量!' |
|
break |
|
} |
|
if (e.finalPrice === '') { |
|
this.err = 'finalPrice' + suf |
|
msg = '请输入成交价!' |
|
break |
|
} |
|
} |
|
if (msg) return this.$util.errMsg(msg) |
|
if (this.orderRepeat.length) return this.$util.errMsg(this.repeatMsg) // 有重复订单不能提交 |
|
this.submiting = true |
|
list.forEach(e => { |
|
e.edited = 1 // 未编辑过的标识,编辑过了的产品在编辑产品页不再显示 |
|
}) |
|
uni.setStorageSync('courses', this.courses) |
|
uni.redirectTo({ |
|
url: `../orderDetail/orderDetail?edited=1` |
|
}) |
|
}, |
|
} |
|
} |
|
</script> |
|
|
|
<style scoped lang="scss"> |
|
.page { |
|
padding-bottom: 130rpx; |
|
-webkit-overflow-scrolling: touch; |
|
} |
|
.block { |
|
position: relative; |
|
padding: 0; |
|
.l-title { |
|
margin: 0 24rpx; |
|
} |
|
|
|
.type-wrap { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
.batch { |
|
display: inline-flex; |
|
align-items: center; |
|
.deadline, .unit { |
|
font-size: 28rpx; |
|
color: #333; |
|
} |
|
.deadline { |
|
width: 130rpx; |
|
} |
|
.unit { |
|
min-width: 80rpx; |
|
text-align: center; |
|
} |
|
} |
|
} |
|
.pro-name { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
padding: 14rpx 24rpx; |
|
font-size: 30rpx; |
|
color: #333; |
|
background: linear-gradient(90deg, #FFF5E5 0%, #FFFFFF 100%); |
|
.left { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
.icon { |
|
width: 60rpx; |
|
height: 60rpx; |
|
margin-right: 12rpx; |
|
border-radius: 10rpx; |
|
} |
|
} |
|
.form-list { |
|
padding: 0 24rpx; |
|
border-top: 0; |
|
.period { |
|
text-align: center; |
|
} |
|
.unit { |
|
display: inline-flex; |
|
align-items: center; |
|
.icon { |
|
width: 28rpx; |
|
margin-left: 20rpx; |
|
} |
|
} |
|
} |
|
</style>
|
|
|