<template> <div class="salesNewEdit-wrap"> <a-spin :spinning="spinning" tip="Loading..."> <a-page-header :ghost="false" :backIcon="false" @back="handleBack" > <!-- 自定义的二级文字标题 --> <template slot="subTitle"> <a id="salesEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a> <span style="margin: 0 15px;color: #666;font-weight: bold;">单号:{{ detailData&&detailData.salesBillNo }}</span> <span v-if="detailData&&detailData.salesBillNoSource">(原:{{ detailData&&detailData.salesBillNoSource || '--' }})</span> <span style="margin: 0 10px;color: #666;">客户名称:{{ detailData&&detailData.buyerName }}</span> <a-button type="link" size="small" class="button-default" @click="showDetail=!showDetail"> <a-icon :type="showDetail ? 'eye-invisible' : 'eye'"/> {{ showDetail?'隐藏':'查看' }}信息 </a-button> </template> </a-page-header> <!-- 单据详情 --> <a-card size="small" :bordered="false" class="salesEdit-cont" v-show="showDetail"> <div style="padding: 10px;"> <a-descriptions size="small" :column="3"> <a-descriptions-item label="客户名称">{{ detailData&&detailData.buyerName || '--' }}</a-descriptions-item> <a-descriptions-item label="收货地址" :span="2">{{ shippingAddress||'--' }}</a-descriptions-item> <a-descriptions-item label="收货人">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeName || '--' }}</a-descriptions-item> <a-descriptions-item label="收货电话">{{ detailData&&detailData.salesBillExtEntity&&detailData.salesBillExtEntity.consigneeTel || '--' }}</a-descriptions-item> <a-descriptions-item label="收款方式">{{ detailData&&detailData.settleStyleSnDictValue || '--' }}</a-descriptions-item> <a-descriptions-item label="审核时间">{{ detailData&&detailData.auditDate || '--' }}</a-descriptions-item> <a-descriptions-item label="业务状态">{{ detailData&&detailData.billStatusDictValue || '--' }}</a-descriptions-item> <a-descriptions-item label="财务状态">{{ detailData&&detailData.financialStatusDictValue || '--' }}</a-descriptions-item> <a-descriptions-item label="改单时间" v-if="detailData&&detailData.salesBillSource=='PURCHASE'&&detailData.submitDate">{{ detailData.submitDate }}</a-descriptions-item> <a-descriptions-item label="最新提交时间" v-if="detailData&&detailData.salesBillSource=='SALES'&&detailData.submitDate">{{ detailData.submitDate }}</a-descriptions-item> <a-descriptions-item label="备注" :span="3">{{ detailData&&detailData.remarks || '--' }}</a-descriptions-item> </a-descriptions> </div> </a-card> <!-- 正常产品 --> <a-card size="small" :bordered="false" class="salesEdit-cont" v-if="salesBillSn"> <div style="padding: 10px;"> <productNormalList ref="productNormalList" @insterOk="insterActiveOk" @spinning="e=>spinning=e" @openCpModal="openProductModal" @allThreeStock="searchAllThreeStock" @addActive="addActive" :showTotal="showTotal" :hasActive="activeList.length>0" :detailData="detailData" :warehouseSn="warehouseSn" :salesBillSn="salesBillSn"></productNormalList> </div> </a-card> <!-- 活动产品 --> <a-card size="small" :bordered="false" class="salesEdit-cont" v-for="item in activeList" :key="item.promoRuleSn" v-if="activeList.length" > <div slot="title" style="display: inline-block;width:100%;"> <strong style="margin-right:10px;font-size:14px;">{{ item.promotion.description }}</strong> ({{ item.promotionRule.description }}) <span style="margin-left:20px;color:#00aaff;cursor: pointer;" @click="(event) => {showDesc(event, item)}"> <a-icon :type="item.showDesc ? 'eye-invisible' : 'eye'"/> 活动详情 </span> <span :style="{margin:'0 20px',color:item.disabled?'#14b900':'#ff0800',cursor: 'pointer'}" @click="(event) => {disenablePromp(event, item)}"> <a-icon title="禁用规则" :type="item.disabled?'link':'disconnect'"/> {{ item.disabled ? '启用规则' : '禁用规则' }} </span> </div> <div slot="extra" @click="tooglePanel(item)" style="cursor: pointer;">{{ item.isActive ? '收起' : '展开' }} <a-icon type="caret-right" :rotate="item.isActive ? 90 : 0"/> </div> <div v-show="item.isActive" style="padding: 10px;"> <productList :ref="'productList-'+item.promoRuleSn" :id="item.promoRuleSn" @openCpModal="openProductModal" @insterOk="insterActiveOk" @spinning="e=>spinning=e" @showDesc="v => showDescOk(v,item)" @upActive="upActive" :promo="item" :detailData="detailData" :warehouseSn="warehouseSn" :salesBillSn="salesBillSn"></productList> </div> </a-card> </a-spin> <div class="affix-cont"> <div class="footer-price"> <div></div> <div v-if="detailData"> <div class="totalPrice">总售价:¥<span>{{ toThousands(detailData.totalAmount) }}</span></div> <div> 产品总款数:<strong style="margin-right: 10px;"> {{ detailData.totalCategory }} </strong> 总数量:<strong style="margin-right: 10px;"> {{ detailData.totalQty }} </strong> <!-- 总售价:¥<strong> {{ toThousands(detailData.totalOrigAmount) }}</strong> --> <span style="margin:0 10px;" v-if="detailData.totalDiscountAmount">优惠金额:¥-<strong>{{ Number(detailData.totalDiscountAmount).toFixed(2) }}</strong></span> <a-popover title="优惠明细" @visibleChange="(visible)=>{visible&&getPromYhDetail()}"> <a-button shape="round" size="small" v-if="detailData.totalDiscountAmount">优惠明细</a-button> <div slot="content"> <div v-if="yhDetail"> <div class="yhdetail" style="min-width:300px;margin-bottom: 5px;" v-for="(item,index) in yhDetail.promoMapList" :key="index"> <div class="yhdetail-h" style="font-weight: bold;font-size:14px;">{{ item.description }}</div> <div style="padding-left:10px;" v-for="(sitem,sindex) in item.promoRuleMapList" :key="sindex" v-if="sitem.lossAmount" > <div style="display: flex;justify-content: space-between;"> <span>{{ sitem.promotionRuleTypeDictValue }}:</span> <strong>¥{{ toThousands(sitem.lossAmount) }}</strong> </div> <div class="yhdetail-d" style="color:#999;">{{ sitem.description }}</div> </div> </div> <div class="yhdetail" style="display: flex;justify-content: space-between;"> <span style="font-weight: bold;font-size:14px;">优惠金额:</span> <span style="font-weight: bold;font-size:18px;">¥{{ Number(yhDetail.totalLossAmount).toFixed(2) }}</span> </div> </div> <div style="text-align: center;padding: 20px;" v-else> 正在加载... </div> </div> </a-popover> </div> </div> </div> <div> <a-button size="large" style="padding: 0 40px;" :disabled="spinning" type="primary" class="button-primary" @click="submitResult()" id="productInfoList-handleSubmit">提交</a-button> </div> </div> <!-- 添加产品 --> <chooseProduct ref="chooseProduct" :openModal="showCpModal" @close="closeProductModal" @addProduct="insterProduct"></chooseProduct> <!-- 新活动窗口 --> <newPromoModal :show="showNewActiveModal" :salesBillSn="salesBillSn" :newActiveList="newActiveList" @ok="showNewActiveOk" ></newPromoModal> </div> </template> <script> import { commonMixin } from '@/utils/mixin' import productList from './comps/productList.vue' import productNormalList from './comps/productNormalList.vue' import chooseProduct from './comps/chooseProduct.vue' import newPromoModal from './newPromoModal.vue' import { salesDisablePromo, salesEnablePromoPromo, salesChangePromo } from '@/api/salesDetailNew' import { salesDetailBySn, salesPromoQueryCount, salesWriteSubmit, submitCheck, updateBatch, salesPromoQueryList, salesQueryUnPartPromo, salesPromoValidaSubmit, getThirdStockQty } from '@/api/salesNew' export default { name: 'SalesNewEdit', mixins: [commonMixin], components: { productList, chooseProduct, productNormalList, newPromoModal }, data () { return { spinning: false, activeList: [], // 活动列表 newActiveList: [], // 新活动列表 activeDesKey: {}, // 活动规则详情数据 salesBillSn: null, // 销售单sn detailData: { discountAmount: 0, id: null, salesBillSn: '' }, // 订单基础数据 warehouseSn: undefined, // 仓库sn // 有价格变更前后总金额 updataData: { totalRealAmount: '', totalAmount: '' }, showDetail: false, // 显示详细基本信息 showCpModal: false, // 添加产品弹框 cpCurRefId: '', // 当前操作的活动id disabledActiveOption: null, // 禁用活动选项 yhDetail: null, // 优惠明细 showNewActiveModal: false // 新活动弹框 } }, computed: { // 是否显示统计信息 showTotal () { return this.activeList.length > 0 }, // 详细地址 shippingAddress () { const shippingAddrProvinceName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrProvinceName ? this.detailData.salesBillExtEntity.shippingAddrProvinceName : '' const shippingAddrCityName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCityName ? this.detailData.salesBillExtEntity.shippingAddrCityName : '' const shippingAddrCountyName = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddrCountyName ? this.detailData.salesBillExtEntity.shippingAddrCountyName : '' const shippingAddr = this.detailData && this.detailData.salesBillExtEntity && this.detailData.salesBillExtEntity.shippingAddr ? this.detailData.salesBillExtEntity.shippingAddr : '' if (!shippingAddrProvinceName && !shippingAddrCityName && !shippingAddrCountyName && !shippingAddr) { return '--' } else { return shippingAddrProvinceName + shippingAddrCityName + shippingAddrCountyName + shippingAddr } } }, methods: { // 返回 handleBack () { this.$router.push({ name: 'salesQueryNewList', query: { closeLastOldTab: true } }) }, // 收起展开活动区域 tooglePanel (item) { item.isActive = !item.isActive this.activeList.splice() // 刷新当前表格 if (item.isActive) { const row = this.$refs['productList-' + item.promoRuleSn][0] row && row.resetSearchForm() } }, // 销售单详情 getOrderDetail (flag, callback) { salesDetailBySn({ salesBillSn: this.$route.params.sn }).then(res => { if (res.status == 200) { this.detailData = res.data this.detailData.totalDiscountAmount = Number(this.detailData.totalOrigAmount || 0) - Number(this.detailData.totalAmount || 0) if (callback) { callback() } } if (flag) { this.getActiveList() } }) }, // 优惠明细查看 getPromYhDetail () { salesPromoQueryCount({ salesBillSn: this.$route.params.sn }).then(res => { if (res.status == 200) { this.yhDetail = res.data } }) }, // 轮询判断是否全部加载完了 isAllLoadFinish (mlist) { const nid = setInterval(() => { const ret = [] mlist.map(item => { const da = item.disabled ret.push(da) }) // 加载完了 if (!ret.includes(true)) { clearInterval(nid) this.spinning = false } }, 50) }, // 刷新所有第三方库存 searchAllThreeStock () { this.spinning = true // 刷新正常活动产品列表 this.$refs.productNormalList.searchThreeStockOk() // 刷新所有活动产品列表 const activeList = this.activeList activeList.map(item => { item.isActive = true const row = this.$refs['productList-' + item.promoRuleSn][0] row && row.searchThreeStockOk() }) activeList.splice() this.spinning = false }, // 刷新所有表格数据 updateAllTable (flag) { const activeList = this.activeList.filter(item => item.isActive) const mlist = [] this.spinning = true // 刷新正常产品列表 this.$refs.productNormalList.resetSearchForm() mlist.push(this.$refs.productNormalList) // 刷新所有活动产品列表 activeList.map(item => { const row = this.$refs['productList-' + item.promoRuleSn][0] row && row.resetSearchForm() mlist.push(row) }) // 判断是否全部调用完 this.isAllLoadFinish(mlist) // 是否刷新详情 if (flag) { this.getOrderDetail() } }, // 获取销售单参与的活动列表 async getActiveList () { // 已参与活动列表 const list = await salesPromoQueryList({ salesBillSn: this.$route.params.sn }).then(res => res.data || []) this.activeList = list.filter(item => item.promotion && item.promotionRule) this.activeList.map(item => { item.isActive = item.enabledFlag == 1 item.showDesc = false item.disabled = item.enabledFlag == 0 this.activeDesKey['search-' + item.promoRuleSn] = false }) setTimeout(() => { this.updateAllTable() }, 500) }, // 获取是否有新活动,有则弹出弹框 async getNewActive () { const hasNewActive = await salesQueryUnPartPromo({ salesBillSn: this.$route.params.sn, enabledFlag: '1' }).then(res => res.data) if (hasNewActive.length) { this.newActiveList = hasNewActive this.showNewActiveModal = true } }, // 新活动弹框,确认 showNewActiveOk () { this.showNewActiveModal = false this.getOrderDetail(true) }, // 添加产品后,关闭弹框 closeProductModal (type) { this.cpCurRefId = '' this.showCpModal = false }, // 打开选择产品弹框 openProductModal (type, refId, countData) { const promo = this.activeList.find(item => item.promoRuleSn == refId) if (promo) { promo.countData = countData } this.$refs.chooseProduct.pageInit(this.detailData, promo, type) this.cpCurRefId = 'productList-' + refId this.showCpModal = true }, // 添加活动产品成功的回调 insterActiveOk (type) { const mlist = [] this.spinning = true // 如果时活动产品 if (type == 'promo') { // 刷新正常产品列表 this.$refs.productNormalList.resetSearchForm() mlist.push(this.$refs.productNormalList) } // 如果时正常产品 if (type == 'normal') { // 刷新活动产品列表 const activeList = this.activeList.filter(item => item.isActive) activeList.map(item => { const row = this.$refs['productList-' + item.promoRuleSn][0] row && row.resetSearchForm() mlist.push(row) }) } // 判断是否全部调用完 this.isAllLoadFinish(mlist) // 重新获取详情信息 this.getOrderDetail() }, // 单击新增产品 insterProduct (row, promotionFlag, type) { // 正常产品 if (type == 0) { this.$refs.productNormalList.insterProduct(row, promotionFlag) } else { // 活动产品 this.$refs[this.cpCurRefId][0].insterProduct(row, promotionFlag, type) } }, // 正常产品添加到活动 addActive (data, params) { const promo = data.split('-') const newSn = this.activeList.find(item => item.promoRuleSn == promo[1]) const newSalesPromoSn = newSn && newSn.salesPromoSn || '' salesChangePromo({ salesPromoSn: newSalesPromoSn, promoRuleSn: promo[1], promotionFlag: promo[2] || '', ...params }).then(res => { if (res.status == 200) { const mlist = [] this.spinning = true // 刷新新参与活动 if (data != 0) { const nt = this.$refs['productList-' + promo[1]][0] nt && nt.resetSearchForm() mlist.push(nt) } // 刷新正常活动 const pnt = this.$refs.productNormalList pnt && pnt.addAcitveSuccess() mlist.push(pnt) // 判断是否全部调用完 this.isAllLoadFinish(mlist) // 刷新详情统计 this.getOrderDetail() } }) }, // 更换活动 upActive (oldPromo, data, params) { const promo = data.split('-') const newSn = this.activeList.find(item => item.promoRuleSn == promo[1]) const newSalesPromoSn = newSn && newSn.salesPromoSn || '' salesChangePromo({ salesPromoSn: data != 0 ? newSalesPromoSn : '', promoRuleSn: promo[1], promotionFlag: promo[2] || '', ...params }).then(res => { if (res.status == 200) { const mlist = [] this.spinning = true // 刷新新参与活动 if (data != 0) { const nt = this.$refs['productList-' + promo[1]][0] nt && nt.resetSearchForm() mlist.push(nt) } // 刷新正常活动 const pnt = this.$refs.productNormalList pnt && pnt.resetSearchForm() mlist.push(pnt) // 刷新当前活动 const ot = this.$refs['productList-' + oldPromo.promoRuleSn][0] ot && ot.upAcitveSuccess() mlist.push(ot) // 判断是否全部调用完 this.isAllLoadFinish(mlist) // 刷新详情统计 this.getOrderDetail() } }) }, // 提交销售单 async submitResult () { const _this = this const data = { salesBillSn: _this.salesBillSn } // 校验活动规则 const vaildActive = await salesPromoValidaSubmit({ salesBillSn: this.salesBillSn }).then(res => res.data) const a = vaildActive.filter(item => item.type == 1) // 不可提交 const b = vaildActive.filter(item => item.type == 0) // 可跳过继续提交 // 弹出不符合规则弹框,不可提交 if (a.length) { this.$info({ title: '提示', centered: true, class: 'confirm-center', okText: '关闭', width: 600, content: <div style="padding-top:15px;"> <ol> {a.map(item => ( <li style="padding:3px 0;">{item.message}</li> ))} </ol> <div style="padding:10px 0;text-align:center"><strong>请按照以上提示修改后再提交</strong></div> </div> }) this.spinning = false } else { // 弹出确认提示信息,可跳过继续提交 if (b.length) { this.$confirm({ title: '提示', centered: true, class: 'confirm-center', okText: '提交', width: 600, content: <div style="padding-top:15px;"> <ol> {b.map(item => ( <li style="padding:3px 0;">{item.message}</li> ))} </ol> </div>, onOk () { _this.submitOrder(data) } }) this.spinning = false } else { _this.submitOrder(data) } } }, // 提交销售单 async submitOrder (data) { this.spinning = true const res = await salesWriteSubmit(data) if (res.status == 200) { this.handleBack() this.$message.success(res.message) } this.spinning = false }, // 展开收缩活动详情 showDesc (e, item) { e.stopPropagation() const row = this.$refs['productList-' + item.promoRuleSn][0] item.promotionRule.minOrderAmount = item.promotion.minOrderAmount ? Number(item.promotion.minOrderAmount).toFixed(2) : '' item.promotionRule.upperLimitAmount = item.promotion.upperLimitAmount ? Number(item.promotion.upperLimitAmount).toFixed(2) : '' row && row.showDesc(item.promotionRule) }, // 展开活动规则详情回调 showDescOk (v, item) { item.showDesc = v if (!item.isActive) { const row = this.$refs['productList-' + item.promoRuleSn][0] row && row.resetSearchForm() item.isActive = true } this.activeList.splice() }, // 启用规则 enabledActive (e, item) { const _this = this this.spinning = true salesEnablePromoPromo({ salesBillSn: _this.salesBillSn, salesPromoSn: item.salesPromoSn }).then(res => { if (res.status == 200) { item.disabled = false item.isActive = true _this.activeList.splice() // 禁用按钮 _this.$refs['productList-' + item.promoRuleSn][0].disableActive(false) // 刷新所有表格 _this.updateAllTable(true) _this.spinning = false _this.$message.success('操作成功,请添加产品') } }) }, // 禁用规则 disabledActive (e, item) { const _this = this _this.spinning = true salesDisablePromo({ salesBillSn: _this.salesBillSn, salesPromoSn: item.salesPromoSn, promoRuleSn: item.promoRuleSn, salesDisableType: _this.disabledActiveOption }).then(res => { if (res.status == 200) { item.disabled = true item.isActive = false _this.activeList.splice() // 启用按钮 _this.$refs['productList-' + item.promoRuleSn][0].disableActive(true) // 刷新所有表格 _this.updateAllTable(true) _this.disabledActiveOption = null _this.spinning = false _this.$message.success('操作成功') } }) }, // 禁用启用活动规则 disenablePromp (e, item) { const _this = this const table = _this.$refs['productList-' + item.promoRuleSn][0] // 是否启用规则 if (item.disabled) { this.enabledActive(e, item) return } // 如果没有活动产品,直接禁用无需弹框提示 if (!table.countData || table.countData && !table.countData.totalQty) { _this.disabledActiveOption = 'DELETE' _this.disabledActive(e, item) return } // 弹框提示禁用方式 this.$confirm({ title: '确定禁用规则?', centered: true, class: 'confirm-center', content: <div> <div style="padding:10px 0;text-align:center;">禁用规则后,将无法享受该活动规则优惠</div> <div style="padding:0 0 10px 0;text-align:center;"> <aRadioGroup onChange={_this.changeDaOpt}> <aRadio style="display:block;height: '30px';lineHeight: '30px';padding:5px 0;" value="DELETE"> 删除规则中相关产品 </aRadio> <aRadio style="display:block;height: '30px';lineHeight: '30px';padding:5px 0;" value="REMOVE"> 移出规则中相关产品 </aRadio> </aRadioGroup> </div> </div>, onOk () { if (_this.disabledActiveOption) { _this.disabledActive(e, item) } else { _this.$message.info('请选择禁用方式!') return true } }, onCancel () { _this.disabledActiveOption = null } }) }, // 选择禁用活动选项 changeDaOpt (e) { this.disabledActiveOption = e.target.value }, // 页面初始化 pageInit () { this.salesBillSn = this.$route.params.sn this.warehouseSn = this.$route.params.sn ? this.$route.params.wSn : '' // 获取销售单详情 this.getOrderDetail(true) // 是否有新活动 this.getNewActive() } }, mounted () { if (!this.$store.state.app.isNewTab) { // 页签刷新时调用 this.pageInit() } }, activated () { // 如果是新页签打开或者进入新的子页(例:存在列表第2条数据编辑页页签时再打开第4条数据的编辑页),则重置当前页面 if (this.$store.state.app.isNewTab || !this.$store.state.app.isNewSubTab) { this.pageInit() } }, beforeRouteEnter (to, from, next) { next(vm => {}) } } </script> <style lang="less"> .salesNewEdit-wrap{ position: relative; height: 100%; padding-bottom: 65px; box-sizing: border-box; >.ant-spin-nested-loading{ overflow-y: auto; height: 100%; } .salesEdit-cont{ margin: 6px 0; } .redStyle{ font-weight: bold; color: red; } .ellipsisCon{ display: flex; justify-content: space-between; align-items: center; .ellipsisText{ width: 100%; overflow: hidden; text-overflow: ellipsis; display: box; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } } .ant-card-small > .ant-card-body { padding: 0!important; } .affix-cont{ padding: 6px 12px; text-align: right; display: flex; justify-content: space-between; align-items: center; .footer-price{ flex-grow:1; display: flex; justify-content: flex-end; align-items: center; > div{ padding: 0 15px; } .totalPrice{ span{ font-weight: bold; color: red; font-size: 20px; } } } } } </style>