#
zhou zhou
2025-12-18 11c52061e55be42d4cd630a49fa2fbde82650f52
pages/order/orderDetlList.vue
@@ -1,17 +1,102 @@
<template>
   <view>
   <view class="page-container">
      <!-- 订单信息头部 -->
      <view class="order-header" v-if="order">
         <view class="header-content">
            <view class="header-row">
               <text class="header-label">单据号</text>
               <text class="header-value">{{order.orderNo}}</text>
            </view>
            <view class="header-row">
               <text class="header-label">单据类型</text>
               <text class="header-value">{{order.docType$ || '-'}}</text>
            </view>
         </view>
      </view>
      <!-- 搜索框 -->
      <view class="search-bar">
         <uni-search-bar v-model="condition" placeholder=" 扫码 / 输入" bgColor="#EEEEEE" @input="search" />
      </view>
      <view class="card" v-show="item.enableQty >0" v-for="item in menuList" @click="chose(item)">
         <view class="tag-item">单据号: {{item.orderNo}}</view>
         <view class="tag-item">物料码: {{item.matnr}}</view>
         <view class="tag-item">物料名称: {{item.maktx}}</view>
         <view class="tag-item">规格: {{item.specs}}</view>
         <view class="tag-item">批次: {{item.batch}}</view>
         <view class="tag-item">数量: {{item.anfme}}</view>
         <view class="tag-item">剩余数量: {{item.enableQty}}</view>
         <uni-search-bar v-model="condition" placeholder=" 扫码 / 输入物料" bgColor="#F5F5F5" @confirm="search" @cancel="onCancelSearch" />
      </view>
      <!-- 明细列表 -->
      <view class="detl-list">
         <view class="detl-card" v-for="(item, index) in filterList" :key="index" @click="chose(item)">
            <!-- 卡片头部 -->
            <view class="card-header">
               <view class="mat-info">
                  <text class="mat-code">{{item.matnr}}</text>
                  <text class="mat-name">{{item.maktx || '-'}}</text>
               </view>
               <view class="qty-badge" :class="item.enableQty > 0 ? 'badge-active' : 'badge-done'">
                  <text class="qty-text">剩余 {{item.enableQty}}</text>
               </view>
            </view>
            <!-- 卡片内容 -->
            <view class="card-body">
               <view class="info-grid">
                  <view class="info-item">
                     <text class="info-label">规格</text>
                     <text class="info-value">{{item.specs || '-'}}</text>
                  </view>
                  <view class="info-item">
                     <text class="info-label">批次</text>
                     <text class="info-value">{{item.batch || '-'}}</text>
                  </view>
                  <view class="info-item">
                     <text class="info-label">订单数量</text>
                     <text class="info-value highlight">{{item.anfme}}</text>
                  </view>
                  <view class="info-item">
                     <text class="info-label">已完成</text>
                     <text class="info-value">{{item.anfme - item.enableQty}}</text>
                  </view>
               </view>
               <!-- 进度条 -->
               <view class="progress-wrap">
                  <view class="progress-bar">
                     <view class="progress-fill" :style="{width: getProgress(item) + '%'}"></view>
                  </view>
                  <text class="progress-text">{{getProgress(item)}}%</text>
               </view>
            </view>
            <!-- 卡片底部 -->
            <view class="card-footer" v-if="item.enableQty > 0">
               <text class="action-text">点击组托入库</text>
               <uni-icons type="right" size="14" color="#667eea"></uni-icons>
            </view>
            <view class="card-footer card-footer-done" v-else>
               <text class="done-text">已完成</text>
               <uni-icons type="checkmarkempty" size="14" color="#28a745"></uni-icons>
            </view>
         </view>
      </view>
      <!-- 空状态 -->
      <view class="empty-state" v-if="filterList.length === 0 && !loading">
         <uni-icons type="info" size="60" color="#CCCCCC"></uni-icons>
         <text class="empty-text">暂无明细数据</text>
      </view>
      <!-- 统计信息 -->
      <view class="stats-bar" v-if="menuList.length > 0">
         <view class="stats-item">
            <text class="stats-value">{{menuList.length}}</text>
            <text class="stats-label">总明细</text>
         </view>
         <view class="stats-divider"></view>
         <view class="stats-item">
            <text class="stats-value">{{pendingCount}}</text>
            <text class="stats-label">待处理</text>
         </view>
         <view class="stats-divider"></view>
         <view class="stats-item">
            <text class="stats-value">{{completedCount}}</text>
            <text class="stats-label">已完成</text>
         </view>
      </view>
   </view>
</template>
@@ -20,93 +105,158 @@
   export default {
      data() {
         return {
            data:'',
            condition:'',
            data: '',
            condition: '',
            menuList: [],
            order:'',
            order: '',
            baseUrl: '',
            token: '',
            loading: false,
         }
      },
      computed: {
         // 过滤后的列表(优先显示有剩余数量的)
         filterList() {
            if (!this.condition.trim()) {
               // 排序:有剩余数量的排前面
               return [...this.menuList].sort((a, b) => {
                  if (a.enableQty > 0 && b.enableQty <= 0) return -1;
                  if (a.enableQty <= 0 && b.enableQty > 0) return 1;
                  return 0;
               });
            }
            const keyword = this.condition.toLowerCase();
            return this.menuList.filter(item => {
               return (item.matnr && item.matnr.toLowerCase().includes(keyword)) ||
                     (item.maktx && item.maktx.toLowerCase().includes(keyword)) ||
                     (item.batch && item.batch.toLowerCase().includes(keyword));
            });
         },
         // 待处理数量
         pendingCount() {
            return this.menuList.filter(item => item.enableQty > 0).length;
         },
         // 已完成数量
         completedCount() {
            return this.menuList.filter(item => item.enableQty <= 0).length;
         }
      },
      onLoad() {
         let that = this
         let that = this;
         const eventChannel = this.getOpenerEventChannel();
         eventChannel.on('data', function(data) {
            that.order = data.data
            that.getOrderNoList(that.order)
         });
         if (eventChannel) {
            eventChannel.on('data', function(data) {
               that.order = data.data;
               that.getOrderNoList(that.order);
            });
         }
      },
      onShow() {
         let that = this
         this.baseUrl = uni.getStorageSync('baseUrl');
         this.token = uni.getStorageSync('token');
         that.getOrderNoList(that.order)
         if (this.order) {
            this.getOrderNoList(this.order);
         }
      },
      methods: {
         search(){
            let that = this
         // 计算进度
         getProgress(item) {
            if (!item.anfme || item.anfme === 0) return 0;
            const progress = ((item.anfme - item.enableQty) / item.anfme * 100).toFixed(0);
            return Math.min(100, Math.max(0, progress));
         },
         // 搜索
         search() {
            if (!this.condition.trim()) {
               this.getOrderNoList(this.order);
               return;
            }
            let that = this;
            that.loading = true;
            uni.request({
                url: that.baseUrl + '/orderDetl/search/pda/auth',
                data: {
               url: that.baseUrl + '/orderDetl/search/pda/auth',
               data: {
                  condition: that.condition,
                  order: that.order.orderNo
                },
               // method:"GET",
                header: {
                  'token':uni.getStorageSync('token'),
                },
               },
               header: {
                  'token': uni.getStorageSync('token'),
               },
               success(result) {
                  console.log(result);
                  var res = result.data
                  if (res.code === 200 ) {
                     that.menuList = res.data
                     // that.save()
                  } else if (res.code == 403) {
                     uni.showToast({title: res.msg, icon: "none", position: 'top'})
                  var res = result.data;
                  if (res.code === 200) {
                     that.menuList = res.data || [];
                  } else if (res.code === 403) {
                     uni.showToast({ title: res.msg, icon: "none", position: 'top' });
                     setTimeout(() => {
                        uni.reLaunch({
                           url: '../login/login'
                        });
                        uni.reLaunch({ url: '../login/login' });
                     }, 1000);
                  } else {
                     uni.showToast({title: res.msg, icon: "none",position: 'top'})
                     uni.showToast({ title: res.msg, icon: "none", position: 'top' });
                  }
               },
               fail() {
                  uni.showToast({ title: '搜索请求失败', icon: "none", position: 'top' });
               },
               complete() {
                  that.loading = false;
               }
            });
         },
         // 取消搜索
         onCancelSearch() {
            this.condition = '';
            this.getOrderNoList(this.order);
         },
         // 获取订单明细列表
         getOrderNoList(order) {
            let that = this
            if (!order || !order.orderNo) return;
            let that = this;
            that.loading = true;
            uni.request({
               url: uni.getStorageSync('baseUrl') + '/orderDetl/list/pda/auth',
               url: uni.getStorageSync('baseUrl') + '/order/pakin/orderDetl/list/pda/auth',
               method: 'POST',
               data: {
               header: {
                  'token': uni.getStorageSync('token'),
               },
               data: {
                  orderNo: order.orderNo
               },
               success(res) {
                  res = res.data
                  that.menuList = res.data
                  res = res.data;
                  if (res.code === 200) {
                     that.menuList = res.data || [];
                  } else {
                     that.menuList = res.data || [];
                  }
               },
               fail() {
                  uni.showToast({ title: '获取明细失败', icon: "none", position: 'top' });
               },
               complete() {
                  that.loading = false;
               }
            })
            });
         },
         // 选择明细进行组托
         chose(item) {
            let that = this
            if (item.enableQty <= 0) {
               uni.showToast({ title: '该明细已完成', icon: "none", position: 'top' });
               return;
            }
            let that = this;
            uni.navigateTo({
               url: "../order/orderPakin2",
               success: function(res) {
                  // 通过eventChannel向被打开页面传送数据   向另外一个页面传递值的
                  res.eventChannel.emit('orderItem', {
                     item: item
                  })
                  });
               },
               events: {
                  // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据  另外一个页面传过来的
                  acceptDataFromOpenedPage: function(data) {
                     // that.matnr = data.data
                     // that.input(that.matnr)
                     // 返回后刷新数据
                  },
               },
            });
         }
      }
@@ -114,19 +264,261 @@
</script>
<style>
   .card {
      margin: 20rpx;
      padding: 30rpx;
      background-color: #157ec1;
      border-radius: 20rpx;
      color: #FFF;
   .page-container {
      min-height: 100vh;
      background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
      padding-bottom: 120rpx;
   }
   .tag-item {
      width: 100%;
      min-height: 60rpx;
      line-height: 2;
      padding-left: 50rpx;
   /* 订单头部 */
   .order-header {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      padding: 16rpx 20rpx;
   }
   .header-content {
      background: rgba(255, 255, 255, 0.15);
      border-radius: 10rpx;
      padding: 12rpx 16rpx;
   }
   .header-row {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 4rpx 0;
   }
   .header-label {
      font-size: 24rpx;
      color: rgba(255, 255, 255, 0.7);
   }
   .header-value {
      font-size: 26rpx;
      color: #ffffff;
      font-size: 14px;
      font-weight: 500;
   }
   /* 搜索栏 */
   .search-bar {
      padding: 0rpx 14rpx;
      background: #ffffff;
      box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
   }
   /* 明细列表 */
   .detl-list {
      padding: 0 20rpx;
   }
   .detl-card {
      background: #ffffff;
      border-radius: 12rpx;
      margin-top: 12rpx;
      box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
      overflow: hidden;
      transition: transform 0.2s ease;
   }
   .detl-card:active {
      transform: scale(0.98);
   }
   /* 卡片头部 */
   .card-header {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      padding: 14rpx 16rpx;
      border-bottom: 1rpx solid #f0f0f0;
   }
   .mat-info {
      flex: 1;
      padding-right: 12rpx;
   }
   .mat-code {
      font-size: 26rpx;
      color: #303133;
      font-weight: 600;
      display: block;
   }
   .mat-name {
      font-size: 22rpx;
      color: #909399;
      margin-top: 4rpx;
      display: block;
   }
   .qty-badge {
      padding: 4rpx 12rpx;
      border-radius: 16rpx;
      flex-shrink: 0;
   }
   .badge-active {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
   }
   .badge-done {
      background: #e8f5e9;
   }
   .qty-text {
      font-size: 20rpx;
      font-weight: 500;
      color: #ffffff;
   }
   .badge-done .qty-text {
      color: #28a745;
   }
   /* 卡片内容 */
   .card-body {
      padding: 12rpx 16rpx;
   }
   .info-grid {
      display: flex;
      flex-wrap: wrap;
   }
   .info-item {
      width: 50%;
      margin-bottom: 8rpx;
   }
   .info-label {
      font-size: 20rpx;
      color: #909399;
      display: block;
   }
   .info-value {
      font-size: 24rpx;
      color: #303133;
      font-weight: 500;
      display: block;
      margin-top: 2rpx;
   }
   .info-value.highlight {
      color: #667eea;
      font-weight: 600;
   }
   /* 进度条 */
   .progress-wrap {
      display: flex;
      align-items: center;
      margin-top: 8rpx;
   }
   .progress-bar {
      flex: 1;
      height: 8rpx;
      background: #e8e8e8;
      border-radius: 4rpx;
      overflow: hidden;
   }
   .progress-fill {
      height: 100%;
      background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
      border-radius: 4rpx;
      transition: width 0.3s ease;
   }
   .progress-text {
      font-size: 20rpx;
      color: #909399;
      margin-left: 12rpx;
      min-width: 50rpx;
      text-align: right;
   }
   /* 卡片底部 */
   .card-footer {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      padding: 12rpx 16rpx;
      border-top: 1rpx solid #f0f0f0;
      background: #fafafa;
   }
   .card-footer-done {
      background: #f0fff4;
   }
   .action-text {
      font-size: 24rpx;
      color: #667eea;
      margin-right: 6rpx;
      font-weight: 500;
   }
   .done-text {
      font-size: 24rpx;
      color: #28a745;
      margin-right: 6rpx;
   }
   /* 空状态 */
   .empty-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 60rpx 0;
   }
   .empty-text {
      font-size: 26rpx;
      color: #909399;
      margin-top: 20rpx;
   }
   /* 统计栏 */
   .stats-bar {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      display: flex;
      align-items: center;
      justify-content: space-around;
      background: #ffffff;
      padding: 16rpx 0;
      box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
   }
   .stats-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      flex: 1;
   }
   .stats-value {
      font-size: 32rpx;
      color: #303133;
      font-weight: 600;
   }
   .stats-label {
      font-size: 20rpx;
      color: #909399;
      margin-top: 4rpx;
   }
   .stats-divider {
      width: 1rpx;
      height: 50rpx;
      background: #e8e8e8;
   }
</style>