<template> <div> <div class="filters mb-10" v-if="showFilter"> <template v-if="!type"> {{$t('运输方式')}} <dict-selector :type='DICT_TYPE.ECW_TRANSPORT_TYPE' v-model="transportType" :placeholder="$t('请选择运输方式')" :filter="transportFilter" style="width:150px" /> </template> {{$t('始发地')}}: <el-select :placeholder="$t('请选择始发地')" v-model="exportCity" clearable> <el-option v-for="item in exportCityList" :key="item.id" :label="item.titleZh" :value="item.id" /> </el-select> {{$t('目的地')}}: <el-select :placeholder="$t('请选择目的地')" v-model="importCity" clearable> <el-option v-for="item in importCityList" :key="item.id" :label="item.titleZh" :value="item.id" /> </el-select> <template v-if="type != 'sea'"> {{$t('出货渠道')}}: <el-select :placeholder="$t('请选择目渠道')" v-model="channelId" clearable> <el-option v-for="item in channelList" :key="item.channelId" :label="item.nameZh" :value="item.channelId" /> </el-select> </template> </div> <div class="mb-10 flex-row" v-if="showFilter"> <el-radio-group v-model="checkAll"> <el-radio :label="true">{{$t('全选')}}</el-radio> <el-radio :label="false">{{$t('全不选')}}</el-radio> </el-radio-group> <el-link class="ml-20" type="danger">{{$t('已选择{n}条路线', {n: selectedRoutes.length})}}</el-link> </div> <el-row class="" :gutter="10"> <template v-for="(item, index) in filteredRouterList"> <el-col :span="12" :key="item.value"> <el-card class="mb-10"> <div slot="header"> {{$l(item, 'label')}} <el-link type="primary" @click.native="toggleHide(item.value)" style="float:right">{{item._hide ? $t('展开') : $t('折叠')}}</el-link> </div> <!--table需要给一个key,否则全选的时候不会自动更新渲染--> <el-table v-if="!hideMap[item.value]" :data="item.routerList" :span-method="SpanMethod" border :key="item.value"> <el-table-column :label="$t('始发仓')" prop="startTitleZh"> <template slot-scope="{row}"> {{$l(row, 'startTitle')}} </template> </el-table-column> <el-table-column :label="$t('目的仓')" prop="destTitleZh" > <template slot-scope="{row}"> {{$l(row, 'destTitle')}} </template> </el-table-column> <el-table-column :label="$t('渠道')" prop="startTitleZh" v-if="[3,4].indexOf(+item.value) > -1"> <template slot-scope="{row}"> {{$l(row.channel, 'name')}} </template> </el-table-column> <el-table-column v-if="showAttr" :label="$t('商品特性')" prop="startTitleZh"> <template slot-scope="{row}"> <!--{{ getAttrNames(row.attrId) }}--> <template v-if="row.channel && row.channel.attrNameList"> {{row.channel.attrNameList.join(',')}} </template> </template> </el-table-column> <el-table-column :label="$t('操作')" prop=""> <template slot="header"> <el-checkbox @change="toggleGroupChecker(index, $event)" v-model="groupChecker[item.value]"></el-checkbox> </template> <template slot-scope="{row}"> <!--给一个Key让他在全选后更新渲染--> <el-checkbox :key="getSelectedIndex(row)" :checked="getSelectedIndex(row) > -1" @change="toggleChecker(row, $event)"></el-checkbox> </template> </el-table-column> </el-table> </el-card> </el-col> </template> </el-row> </div> </template> <script> import {getChannelList} from '@/api/ecw/channel' import {getTradeCityList} from '@/api/ecw/region' import {openedRouterList} from '@/api/ecw/warehouse' import {getProductAttrList} from "@/api/ecw/productAttr"; import Template from "@/views/cms/template"; export default { components: {Template}, props:{ value: { type: Array }, option: Object, // 类型,sea海运,air空运 type: String, showFilter:{ type: Boolean, default: true } }, data(){ return { transportTypeDicts: this.getDictDatas(this.DICT_TYPE.ECW_TRANSPORT_TYPE), channelList:[], tradeCityList:[], openedRouterList:[], // 开放路线 transportType: null, // 运输方式 importCity: null, // 目的地(进口城市) exportCity: null, // 始发地(出口城市) channelId: null, selectedRoutes: [], // 勾选的路线渠道 hideMap: {}, // 折叠状态 checkAll: null, groupChecker: {}, // 分组全选状态 attrList:[], // 商品特性 inited: false } }, computed:{ importCityList(){ return this.tradeCityList.filter(item => item.type == 1 || item.type == 3) }, exportCityList(){ return this.tradeCityList.filter(item => item.type == 2 || item.type == 3) }, exportCityIds(){ let ids = [] this.exportCityList.forEach(item => { ids.push(item.id) }) return ids }, importCityIds(){ let ids = [] this.importCityList.forEach(item => { ids.push(item.id) }) return ids }, // 根据选择的渠道筛选 availChannelList(){ return this.channelList.filter(item => !this.channelId || this.channelId == item.channelId) }, filteredRouterList(){ let transportTypeList = [] this.transportTypeDicts .filter(this.transportFilter) .filter(transport => !this.channelId || transport.cssClass == 'channel') .forEach(item => { if(this.transportType === null || this.transportType == '' || this.transportType == item.value){ let routerList = [] this.openedRouterList.forEach(router => { if(router.transportType == item.value){ let availChannels = [] // 空运相关的,没有可用的渠道则不显示线路 if(item.cssClass === 'channel'){ availChannels = this.availChannelList.filter(channel => channel.countryId == router.destCountryId) if(!availChannels.length) return } routerList.push(Object.assign({ _merge: item.cssClass == 'channel' ? availChannels.length || 1 : 1, channel: item.cssClass == 'channel' ? availChannels[0] || { channelId: 0} : {channelId: 0}, }, router) ) // 字典的cssClass =channel则表示渠道相关(空运,海空联运) if(item.cssClass == 'channel'){ availChannels.slice(1).forEach(channel => { routerList.push(Object.assign({channel, _merge: 0}, router)) }) } } }) let child = { label: item.label, labelEn: item.labelEn, value: item.value, _hide: false, // 是否折叠 routerList: routerList } transportTypeList.push(child) } }) return transportTypeList }, // 是否显示商品特性(渠道) showAttr(){ return this.type == 'air' }, // 显示产品特性 getAttrName(){ return (id) => { let item = this.attrList.find(item => item.id === +id) if(!item) return '' return this.$l(item, 'attrName') } }, // 显示多个商品特性 getAttrNames(){ return (ids) => { if(!ids) return '' return ids.split(',').filter( item => !!item).map(id => this.getAttrName(id)).join(',') } } }, watch:{ exportCity(){ this.getOpenedRouterList() }, importCity(){ this.getChannelList() this.getOpenedRouterList() }, selectedRoutes(val){ this.$emit('input', val) // 如果选择发生变化 let total = 0 this.filteredRouterList.forEach(item => { total += item.routerList.length }) if(total != val.length && val.length){ this.checkAll = null } }, value(val){ this.selectedRoutes = val || [] }, checkAll(val){ if(val === true || val === false){ console.log('选中全部') this.filteredRouterList.forEach(item => { item.routerList.forEach(router => { if(this.getSelectedIndex(router) > -1 != val )this.toggleChecker(router, val) }) }) } }, option(option){ if(option){ this.changeOption() } }, // 显示的路线发生变化之后,清空已勾选的路线 filteredRouterList(){ if(this.inited){ this.selectedRoutes = [] Object.keys(this.groupChecker).forEach(key => { this.groupChecker[key] = false }) } } }, async created(){ this.getChannelList() this.tradeCityList = (await getTradeCityList()).data // 路线需要过滤失效的进出口城市,所以在程序加载后再加载路线 await this.getOpenedRouterList() if(this.option){ this.changeOption() } await this.$nextTick() if(this.value && this.value.length){ this.selectedRoutes = this.value } // 如果显示特性,则需要查询特数据备用 if(this.showAttr){ this.getAttrList() } await this.$nextTick() this.inited = true }, methods:{ async getChannelList(){ let query = { cityId: this.importCity } this.channelList = (await getChannelList(query)).data }, getAttrList(){ getProductAttrList().then(res => { this.attrList = res.data }) }, changeOption(){ if(!this.option) return this.importCity = +this.option.importCity || null this.exportCity = +this.option.exportCity || null this.transportType = this.option.transportId || null this.channelId = +this.option.channelId || null }, // 全选、全不选 某个运输方式所有线路 toggleGroupChecker(index, selected){ let routerList = this.filteredRouterList[index].routerList console.log(routerList.length, selected) routerList.forEach(router => { this.toggleChecker(router, selected) }) }, async getOpenedRouterList(){ let params = {} if(this.exportCity){ params.startCityId = this.exportCity } if(this.importCity){ params.destCityId = this.importCity } const res = await openedRouterList(params) this.openedRouterList = res.data.filter(item => { return this.exportCityIds.indexOf(item.startCityId) > -1 && this.importCityIds.indexOf(item.destCityId) > -1 }) }, // 切换路线选择 toggleChecker(router, selected){ // this.getSelectedIndex(router) /* this.selectedRoutes.forEach((item, i)=>{ if(item.lineId == router.id && item.shippingChannelId == item.channel.id){ index = i break } }) */ if(selected){ // 先判断是否已勾选 if(this.getSelectedIndex(router) > -1) return this.selectedRoutes.push({ lineId: router.id, shippingChannelId: router.channel.channelId, transportId: router.transportType }) }else{ let index = this.getSelectedIndex(router) if(index > -1){ this.selectedRoutes.splice(index, 1) } } }, getSelectedIndex(router){ return this.selectedRoutes.findIndex(item => { return item.lineId == router.id && item.shippingChannelId == router.channel.channelId }) }, SpanMethod({ row, column, rowIndex, columnIndex }){ if (columnIndex < 2 ) { return { rowspan: row._merge, colspan: 1 } } return { rowspan: 1, colspan: 1 } }, // 折叠,展开 toggleHide(value){ this.$set(this.hideMap, value, !this.hideMap[value]) }, // 运输方式筛选 transportFilter(item){ // 未指定类型则全部可用 if(!this.type) return true return (this.type == 'sea' ? ['1','2'] : ['3', '4']).indexOf(item.value) > -1 }, } } </script> <style scoped> .mb-10{ margin-bottom: 10px } </style>