grab-record.vue 12.9 KB
<template>
  <Page name="grab-record" flank>
    <template #header>
      <u-tabs :current="currentTab" :list="navbarList" @click="onScrollCheckChange" :scrollable="false" :disabled="loading" :activeStyle="{ color: '#1E7B6B' }"> </u-tabs>
      <view class="line"></view>
      <view class="quick-tag">
        <view class="quick-tag-group">
          <view class="quick-tag-item" :class="searchForm.vehicleLicenseNum ? 'active' : ''" @click="onSelectPlate">
            <view class="value">{{ searchForm.vehicleLicenseNum || '车牌号' }}</view>
            <view @click.stop="clearSearchForm('vehicleLicenseNum')" v-if="searchForm.vehicleLicenseNum" style="width: 10px; padding: 0 2px">
              <u-icon name="close-circle"></u-icon>
            </view>
            <view v-else class="sx-img">
              <image class="sx-image" :src="formatImagePath('down')"></image>
            </view>
          </view>
          <view class="quick-tag-item" :class="searchForm.driverName ? 'active' : ''" @click="selectQuickTag({ key: 'driverName', value: searchForm.driverName })">
            <view class="value">{{ searchForm.driverName || '司机姓名' }}</view>
            <view @click.stop="clearSearchForm('driverName')" v-if="searchForm.driverName" style="width: 10px; padding: 0 2px">
              <u-icon name="close-circle"></u-icon>
            </view>
            <view v-else class="sx-img">
              <image class="sx-image" :src="formatImagePath('down')"></image>
            </view>
          </view>
          <view class="quick-tag-item" :class="searchForm.driverMobile ? 'active' : ''" @click="selectQuickTag({ key: 'driverMobile', value: searchForm.driverMobile })">
            <view class="value">{{ searchForm.driverMobile || '司机手机' }}</view>
            <view @click.stop="clearSearchForm('driverMobile')" v-if="searchForm.driverMobile" style="width: 10px; padding: 0 2px">
              <u-icon name="close-circle"></u-icon>
            </view>
            <view v-else class="sx-img">
              <image class="sx-image" :src="formatImagePath('down')"></image>
            </view>
          </view>
          <view @click="sortChange"><text style="color: #999; margin-right: 6rpx">抢单时间</text><zui-icon name="switch-vertical"></zui-icon></view>
        </view>
      </view>
    </template>
    <template #content>
      <List ref="list" v-model="list" :loading.sync="loading" :api="searchAPI">
        <view v-for="(form, index) in list" :key="index">
          <view class="card">
            <view style="position: absolute; top: 24rpx; right: 24rpx" :style="{ color: statusMap[form.status] }">
              <render-dict :value="form.status" dict="FREIGHT_GOODS_SOURCE_BIDDING_STATUS"></render-dict>
            </view>
            <view-item title="订单号" v-if="form.orderCode && form.status === 'ASSIGNED'">
              <view @click="toDetail(form.orderCode)" class="color-blue">{{ form.orderCode }}</view>
              <field-copy :value="form.orderCode"> </field-copy>
            </view-item>
            <view-item title="抢单司机">
              <field-call :value="form.driverMobile">
                <text>{{ form.driverName || '' }}{{ form.driverMobile || '' }}</text>
              </field-call>
            </view-item>
            <view-item title="抢单车辆">
              <text>
                <render-dict :value="form.specification" dict="VEHICLE_SPECIFICATION"></render-dict>
              </text>
              <text>
                <render-dict :value="form.vanType" dict="VEHICLE_COMPARTMENT_TYPE"></render-dict>
              </text>
              <text>{{ form.vehicleLicenseNum }}</text>
              <text v-if="form.trailerLicenseNum">/{{ form.trailerLicenseNum }}</text>
            </view-item>
            <view-item title="抢单时间" :value="form.biddingTime"></view-item>
            <view-item title="装卸吨位">
              <text>{{ form.biddingWeight || '--' }}吨</text>
            </view-item>
            <view class="buts">
              <view>
                <text>价格:</text>
                <text class="color-red">{{ form.priceType === 'TON' ? form.weightUnitPrice : form.vehicleUnitPrice }}</text>
                <text>{{ form.priceType === 'TON' ? '元/吨' : '元/车' }}</text>
              </view>
              <view style="display: flex; gap: 24rpx; justify-content: space-between" v-if="form.status === 'WAIT_ASSIGN'">
                <zui-button v-if="$permission('/freightGoodsSource/cancelBidding')" class="zui-button" @click="(cancelCode = form.code), (cancelRemark = ''), (cancelShow = true)"
                  >取消</zui-button
                >
                <zui-button v-if="$permission('/freightGoodsSource/addOrder')" theme="primary" @click="() => toSubmit(form)">成交指派</zui-button>
              </view>
            </view>
          </view>
        </view>
      </List>
      <u-modal
        :show="driverSearchShow"
        :title="driverSearchKey === 'driverName' ? '司机姓名' : '司机手机'"
        @cancel="driverSearchShow = false"
        show-cancel-button
        @confirm="driverConfirm"
        @close="driverSearchShow = false"
      >
        <u-input v-model="driverStr"> </u-input>
      </u-modal>
      <u-modal :show="cancelShow" title="取消原因" @cancel="cancelShow = false" @confirm="confirmCancel" show-cancel-button>
        <u-input v-model="cancelRemark" placeholder="取消原因"></u-input>
      </u-modal>
      <popup-platenumber :visible="platenumberVisible" v-model="searchForm.vehicleLicenseNum" @update:visible="e => (platenumberVisible = e)" @confirm="onPlatenumberSelect" />
    </template>
  </Page>
</template>

<script>
import page from '@/mixins/page';
import { mapGetters } from 'vuex';
import FieldCopy from '@/components/field/field-copy.vue';
import dayjs from 'dayjs';
export default {
  components: { FieldCopy },
  mixins: [page],
  data() {
    return {
      driverSearchShow: false,
      driverSearchKey: '',
      driverStr: '',
      cancelShow: false,
      cancelCode: '',
      cancelRemark: '',
      currentTab: 0,
      loading: false,
      list: [],
      countMap: {
        waitAssignCount: 0,
        assignedCount: 0,
        cancelledCount: 0,
      },
      orderStatus: 'WAIT_ASSIGN',
      goodsSourceCode: '',
      statusMap: {
        WAIT_ASSIGN: '#F25643',
        ASSIGNED: '#3296FA',
        CANCELLED: '#999999',
      },
      platenumberVisible: false,
      searchForm: {
        vehicleLicenseNum: '',
        driverName: '',
        driverMobile: '',
        sortFlag: false,
      },
    };
  },
  onShow() {
    this.onSearch({ showLoading: true });
  },
  onLoad(options) {
    this.goodsSourceCode = options.goodsSourceCode;
  },
  computed: {
    ...mapGetters(['dictList']),
    navbarList() {
      return [
        { name: `待指派(${this.countMap.waitAssignCount || 0})`, prop: 'WAIT_ASSIGN' },
        { name: `已指派(${this.countMap.assignedCount || 0})`, prop: 'ASSIGNED' },
        { name: `已取消(${this.countMap.cancelledCount || 0})`, prop: 'CANCELLED' },
      ];
    },
  },
  methods: {
    clearSearchForm(label) {
      this.searchForm = Object.assign(this.searchForm, { [label]: '' });
      this.onSearch();
    },
    // 打开车牌选择
    onSelectPlate() {
      this.platenumberVisible = true;
    },
    // 选中车牌
    onPlatenumberSelect(value) {
      this.platenumberVisible = false;
      this.searchForm.vehicleLicenseNum = value;
      this.onSearch({ showLoading: true });
    },
    selectQuickTag({ key, value }) {
      this.driverStr = value;
      this.driverSearchKey = key;
      this.driverSearchShow = true;
    },
    driverConfirm() {
      this.driverSearchShow = false;
      this.searchForm = Object.assign(this.searchForm, { [this.driverSearchKey]: this.driverStr });
      this.onSearch();
    },
    sortChange() {
      this.searchForm = Object.assign(this.searchForm, { sortFlag: !this.searchForm.sortFlag });
      this.onSearch();
    },
    // 查询数据
    searchAPI(params) {
      this.getCount();
      return uni.$u.api.freightGoodsSourceV2.biddingPage({
        ...params,
        ...this.searchForm,
        status: this.orderStatus,
        goodsSourceCode: this.goodsSourceCode,
      });
    },
    // 获取统计数量
    getCount() {
      uni.$u.api.freightGoodsSourceV2.biddingCount({ goodsSourceCode: this.goodsSourceCode }).then(res => {
        let result = res?.result || {};
        Object.keys(this.countMap).forEach(item => {
          this.countMap[item] = result[item] ? result[item] : 0;
        });
      });
    },
    onScrollCheckChange(e) {
      this.currentTab = e.index;
      this.orderStatus = this.navbarList[e.index].prop;
      this.onSearch({ showLoading: true });
    },
    // 确认-发布需求
    toSubmit(item) {
      let form = {
        ...item,
        goodsWeight: item.biddingWeight,
        goodsSourceCode: item.goodsSourceCode,
        goodsSourceBiddingCode: item.code,
        loadTime: dayjs(item.biddingTime).add(3, 'hour').format('YYYY-MM-DD HH:mm:ss'),
        waypoints: [
          {
            cityCode: item.startCityCode,
            areaCode: item.startAreaCode,
            address: item.startAddress,
            lng: item.startLng,
            lat: item.startLat,
          },
          {
            cityCode: item.endCityCode,
            areaCode: item.endAreaCode,
            address: item.endAddress,
            lng: item.endLng,
            lat: item.endLat,
          },
        ],
      };
      uni.navigateTo({
        url: `/pages/order/add?eventCode=${item.code}`,
        success(res) {
          res.eventChannel.emit('get-item', form);
        },
      });
    },
    // 取消
    confirmCancel() {
      if (this.loading) return;
      this.loading = true;
      uni.$u.api.freightGoodsSourceV2
        .cancelBidding({ cancelReason: this.cancelRemark, code: this.cancelCode })
        .then(res => {
          this.cancelShow = false;
          this.loading = false;
          uni.showToast({ title: '取消成功', icon: 'none' });
          this.onSearch({ showLoading: true });
        })
        .catch(() => {
          this.loading = false;
        });
    },
    toDetail(code) {
      uni.navigateTo({ url: '/pages/order/detail?code=' + code });
    },
  },
};
</script>

<style lang="scss">
.page-grab-record {
  &__header {
    padding: 0 !important;
    .line {
      height: 1rpx;
      background: #f6f6f6;
      position: relative;
      top: -5rpx;
    }
    .quick-tag {
      display: flex;
      padding: 15upx 22upx;
      box-sizing: border-box;
      position: relative;
      .quick-tag-group {
        flex: 1;
        display: flex;
        align-items: center;
        background-color: #fff;
        padding-left: $padding-xs !important;
        padding-right: $padding-xs !important;
        overflow-y: auto;
        justify-content: space-between;
        gap: 15rpx;

        .quick-tag-item {
          flex: 1;
          flex-shrink: 0;
          min-width: 158upx;
          height: 58upx;
          background: #f6f6f6;
          border-radius: 8upx;
          font-size: 28upx;
          font-weight: 400;
          color: #2b2a27;
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 0 10upx;
          box-sizing: border-box;
          position: relative;
          &:not(:last-child) {
            //margin-right: 18upx;
          }

          &.active {
            background: #ffffff;
            border-radius: 8upx;
            border: 2upx solid #2673fb;
            font-size: 28upx;
            font-family:
              PingFangSC,
              PingFang SC;
            font-weight: 400;
            color: #2673fb;
          }
          .value {
            white-space: nowrap;
            overflow: hidden;
            flex: 1;
          }
          .sx-img {
            height: 12upx;
            width: 14upx;
            position: relative;
            margin-left: 12upx;

            .sx-image {
              width: 100%;
              height: 100%;
              position: absolute;
              top: 0;
              left: 0;
            }
          }
        }
      }
    }
  }

  &__content {
    padding: 22rpx !important;

    .card {
      padding: 24rpx 0 24rpx 0;
      margin-bottom: 20rpx;
      background: white;
      border-radius: 20rpx;
      position: relative;
      .view-item {
        display: flex;
        margin-bottom: 20rpx;
        font-size: 26rpx;
        .view-item__label {
          padding-left: 26rpx;
          color: #999999;
          width: 170rpx;
        }
        .view-item__value {
          flex: 1;
          color: #2b2a27;
          padding-right: 5rpx;
          display: flex;
          flex-wrap: wrap;
        }
      }
      .view-item:not(:last-child) {
        margin-bottom: 30rpx;
      }
      .buts {
        font-size: 30rpx;
        padding-left: 30rpx;
        padding-right: 24rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
    }
  }
}
</style>