modify.vue 8.16 KB
<template>
  <view class="page">
    <scroll-view class="scroll" scroll-y>
      <uni-list>
        <view class="section">
          <uni-list-item title="要车日期">
            <template v-slot:footer>
              <view class="readonly-text">{{ form.applyDate }}</view>
            </template>
          </uni-list-item>
          <uni-list-item title="所属办">
            <template v-slot:footer>
              <view class="readonly-text">{{ form.deptName }}</view>
            </template>
          </uni-list-item>
        </view>

        <!-- 产品 -->
        <view class="section2">
          <!-- mode="add" 允许编辑 -->
          <Product mode="add" :list="initDelayedShipmentDetailList" @change="delayedShipmentDetailListChange"
            :orderDate="form.orderDate" />
        </view>
        <view class="footer">
          <button class="btn submit" type="primary" @click="onSubmit">保存</button>
        </view>
      </uni-list>
    </scroll-view>
  </view>
</template>

<script>
import { updateApi, getDetailApi } from '@/api/delay_invoice.js'
import Product from './product.vue'

export default {
  name: 'DelayInvoiceModify',
  components: { Product },
  data() {
    return {
      form: {
        id: '',
      },
      initDelayedShipmentDetailList: [],
    }
  },
  onLoad(query) {
    const id = (query && (query.id || query.code)) || ''
    if (id) {
      this.loadDetail(id)
    }
  },
  methods: {
    async loadDetail(id) {
      try {
        const res = await getDetailApi(id)
        const m = res.data || {}
        const next = { ...this.form, ...m }
        // 确保ID存在
        next.id = m.id || id
        // 映射列表
        // 注意:详情返回的是 replenishmentOrderLineList,需要赋值给 initDelayedShipmentDetailList 以便 Product 组件初始化
        // 且需要处理字段兼容性,确保 Product 组件能正确显示和编辑
        const lines = Array.isArray(m.delayedShipmentDetailList) ? m.delayedShipmentDetailList.map(x => ({
           ...x,
           // 确保 Product 组件需要的字段存在
           // Product组件使用: quantity(需发), shippedQuantity(实发), supplementaryQuantity(需求补货), salesPrice(单价)
           // 详情接口返回的字段应该已经包含了这些,如果有差异需要在此处转换
           // 注意:add.vue中 onRelateConfirm 做了映射,这里是回显,通常直接使用即可
        })) : []
        
        this.form = next;
        this.initDelayedShipmentDetailList = lines;
      } catch (e) {
        uni.showToast({ title: '加载失败', icon: 'none' })
      }
    },
    validateLineListRequired() {
      const list = Array.isArray(this.form.delayedShipmentDetailList) ? this.form.delayedShipmentDetailList : []
      if (list.length === 0) {
        uni.showToast({ title: '请先添加产品', icon: 'none' })
        return false
      }
      const fields = [
        { key: 'applyShipmentDate', label: '现申请发货日期' },
      ]
      for (let i = 0; i < list.length; i++) {
        const it = list[i] || {}
        for (const f of fields) {
          const v = it && it[f.key]
          if (v === undefined || v === null || String(v).trim() === '') {
            uni.showToast({ title: `产品第${i + 1}条:${f.label}不能为空!`, icon: 'none' })
            return false
          }
        }
      }
      return true
    },
    async onSubmit() {
      if (!this.validateLineListRequired()) return
      const payload = { ...this.form }
      
      console.log('onSubmit__payload', payload)
      try {
        await updateApi(payload)
        uni.showToast({ title: '保存成功', icon: 'success' })
        setTimeout(() => { uni.redirectTo({ url: '/pages/delay_invoice/index' }) }, 300)
      } catch (e) {
        uni.showToast({ title: (e && e.msg) || '保存失败', icon: 'none' })
      }
    },
    delayedShipmentDetailListChange(data) {
      const list = Array.isArray(data) ? data : []
      this.form.delayedShipmentDetailList = list
    },
  }
}
</script>

<style lang="scss" scoped>
.page {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.scroll {
  flex: 1;
  padding: 6rpx 0 400rpx;
}



.title-header {
  background-color: #fff;
  display: flex;
  align-items: center;
  padding: 32rpx 32rpx 22rpx;

  .title-header_icon {
    width: 32rpx;
    height: 28rpx;
    margin-right: 16rpx;
  }

  span {
    color: rgba(0, 0, 0, 0.9);
    font-size: 32rpx;
    line-height: 44rpx;
    font-weight: 600;
  }
}


.section {
  background: #fff;
  margin-bottom: 20rpx;
}

.section2 {
  background: #f1f1f1;
}

::v-deep .uni-list {
  background: transparent;

  &-item {
    &__extra-text {
      font-size: 32rpx;
    }

    &__content-title {
      font-size: 32rpx;
      color: rgba(0, 0, 0, 0.9);
    }

    &__container {
      padding: 32rpx;
      // align-items: center;

      .uni-easyinput {

        .is-disabled {
          background-color: transparent !important;
        }

        &__placeholder-class {
          font-size: 32rpx;
          color: rgba(0, 0, 0, 0.4);
        }

        &__content {
          border: none;

          &-input {
            padding-left: 0 !important;
            height: 48rpx;
            line-height: 48rpx;
            font-size: 32rpx;
          }

          .content-clear-icon {
            font-size: 44rpx !important;
          }
        }
      }

      .amount-row {
        flex: 1;
        display: flex;
        align-items: center;

        .uni-easyinput {
          flex: 1;
        }

        .unit {
          margin-left: 16rpx;
          color: rgba(0, 0, 0, 0.9);
        }
      }

      .item-title,
      .uni-list-item__content {
        flex: none;
        min-height: 48rpx;
        line-height: 48rpx;
        font-size: 32rpx;
        position: relative;
        width: 210rpx;
        margin-right: 32rpx;
        color: rgba(0, 0, 0, 0.9);
        padding-right: 0;


        .required {
          color: red;
          position: absolute;
          top: 50%;
          transform: translateY(-50%);
          left: -16rpx;
        }
      }

    }

    &.select-item {
      &.is-empty {
        .uni-list-item__extra-text {
          color: rgba(0, 0, 0, 0.4) !important;
        }
      }

      &.is-filled {
        .uni-list-item__extra-text {
          color: rgba(0, 0, 0, 0.9) !important;
        }
      }

      .serial-number-row {
        display: flex;
        align-items: center;
      }

    }

    &.mgb10 {
      margin-bottom: 20rpx;
    }

  }

  .title-header {
    background-color: #fff;
    display: flex;
    align-items: center;
    padding: 32rpx 32rpx 22rpx;

    &_icon {
      width: 32rpx;
      height: 28rpx;
      margin-right: 16rpx;
    }

    span {
      color: rgba(0, 0, 0, 0.9);
      font-size: 32rpx;
      line-height: 44rpx;
      font-weight: 600;
    }
  }
}

/* 只读 easyinput 根据内容自适应高度 */
::v-deep .uni-list-item__container {
  align-items: flex-start;
}

/* 只读文本样式 */
.readonly-text {
  color: rgba(0, 0, 0, 0.9);
  font-size: 32rpx;
  line-height: 48rpx;
  text-align: right;
  white-space: pre-wrap;
  word-break: break-all;
}


.footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0 32rpx 32rpx;
  padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  background: #fff;
  box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  z-index: 10;

  .btn {
    height: 80rpx;
    line-height: 80rpx;
    border-radius: 12rpx;
    font-size: 32rpx;
  }

  .submit {
    background: $theme-primary;
    color: #fff;
  }

  .view-total {
    padding: 20rpx 0;

    .head {
      font-size: 32rpx;
      font-weight: 600;
      line-height: 50rpx;
      color: rgba(0, 0, 0, 0.9);
      padding-bottom: 16rpx;
      margin-bottom: 24rpx;
      border-bottom: 1px dashed #E7E7E7;
    }

    .row {
      display: flex;
      margin-bottom: 24rpx;
      line-height: 32rpx;

      .row2 {
        width: 50%;
      }

      .label {
        width: 180rpx;
        margin-right: 14rpx;
        color: rgba(0, 0, 0, 0.6);
        font-size: 28rpx;
      }

      .value {
        flex: 1;
        color: rgba(0, 0, 0, 0.9);
        font-size: 28rpx;
        white-space: pre-wrap;
        word-break: break-all;
      }
    }
  }
}
</style>