<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> <a-button type="link" 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="备注" :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" @openCpModal="openProductModal" :showTotal="showTotal" :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" @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 60px;" :disabled="spinning" type="primary" class="button-primary" @click="handleSubmit()" id="productInfoList-handleSubmit">提交</a-button> </div> </div> <!-- 添加产品 --> <chooseProduct ref="chooseProduct" :openModal="showCpModal" @close="closeProductModal" @addProduct="insterProduct"></chooseProduct> <!-- 价格更新弹窗 --> <setPriceModal :show="priceUpdateModal" :totalRealAmount="updataData.totalRealAmount" :totalAmount="updataData.totalAmount" @ok="updatePrice" @cancel="priceUpdateModal=false"></setPriceModal> <!-- 新活动窗口 --> <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 setPriceModal from './setPriceModal.vue' import newPromoModal from './newPromoModal.vue' import { salesDisablePromo,salesEnablePromoPromo, salesChangePromo } from '@/api/salesDetailNew' import { salesDetailBySn,salesPromoQueryCount, salesWriteSubmit, submitCheck, updateBatch, salesPromoQueryList, salesQueryUnPartPromo,salesPromoValidaSubmit } from '@/api/salesNew' export default { name: 'SalesNewEdit', mixins: [commonMixin], components:{ setPriceModal, productList, chooseProduct, productNormalList, newPromoModal }, data () { return { spinning: false, activeList:[], // 活动列表 newActiveList: [], // 新活动列表 activeDesKey: {}, salesBillSn: null, // 销售单sn detailData: { discountAmount: 0, id: null, salesBillSn: '' }, // 订单基础数据 warehouseSn: undefined, updataData: { totalRealAmount: '', totalAmount: '' }, priceUpdateModal: false, // 价格更新弹窗 showDetail: false, showCpModal: false, cpCurRefId: '', 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) { 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(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 } console.log(ret) }, 50) }, // 刷新所有表格数据 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(){ // 已参与活动列表 this.activeList = await salesPromoQueryList({ salesBillSn: this.$route.params.sn }).then(res => res.data || []) 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 // 刷新表格 // this.insterActiveOk(['normal','promo'][type]) }, // 打开选择产品弹框 openProductModal(type, refId){ console.log(type, refId) const promo = this.activeList.find(item => item.promoRuleSn == refId) this.$refs.chooseProduct.pageInit(this.detailData, promo, type) this.cpCurRefId = 'productList-' + refId this.showCpModal = true }, // 添加活动产品成功的回调 insterActiveOk(type){ console.log(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) } }, // 更换活动 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() } }) }, // 选择价格类型 并更新 updatePrice (type) { const ajax_data = { salesBillSn: this.salesBillSn, productPriceChangeFlag: type } if (type == 0) { this.submitResult(ajax_data) } else { updateBatch(this.updataData.detailList).then(res => { if (res.status == 200) { this.submitResult(ajax_data) } }) } }, // 提交销售单 handleSubmit () { // 先不提交,先判断是否有价格更新 (下级创建时判断) if (this.detailData&&this.detailData.salesBillSource == 'PURCHASE') { submitCheck({ salesBillSn: this.salesBillSn }).then(res => { if (res.status == 200) { if (res.data.detailList.length > 0) { this.updataData = res.data this.$nextTick(() => { this.priceUpdateModal = true }) } else { this.submitResult({ salesBillSn: this.salesBillSn }) } } }) } else { this.submitResult({ salesBillSn: this.salesBillSn }) } }, // 提交销售单 async submitResult (data) { const _this = this // 校验活动规则 const vaildActive = await salesPromoValidaSubmit({salesBillSn: this.salesBillSn}).then(res => res.data) // console.log(vaildActive) 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> }); }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) } }); }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] 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.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: 75px; box-sizing: border-box; >.ant-spin-nested-loading{ overflow-y: auto; height: 100%; } .salesEdit-cont{ margin: 10px 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: 10px 15px; 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>