zjh
2025-11-12 d99d35d47cc8b120258b6ccd84751a47d9ea2450
产线提交代码上传
已修改1个文件
已添加1个文件
659 ■■■■■ 文件已修改
pages.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/QC/SJ/ProductionLineSubmit.vue 652 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json
@@ -258,6 +258,13 @@
            }
        },
        {
            "path": "pages/QC/SJ/ProductionLineSubmit",
            "style": {
                "navigationBarTitleText": "产线提交",
                "enablePullDownRefresh": false
            }
        },
        {
            "path": "pages/QC/RKJ/List",
            "style": {
                "enablePullDownRefresh": true,
pages/QC/SJ/ProductionLineSubmit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,652 @@
<template>
  <view class="inspection-app">
    <!-- é¡¶éƒ¨æç¤ºæ¡† -->
    <view :class="{ 'tips-ani': tipShow }" class="tips">刷新成功</view>
    <!-- Tab切换 -->
    <view class="filter-section">
      <view class="filter-controls" style="margin-bottom: 5px;">
        <view class="status-tabs">
          <button :class="['tab-button', currentTab === 0 ? 'active' : '']"
                  @click="switchTab(0)">未提交({{ uncheckedCount }})
          </button>
          <button :class="['tab-button', currentTab === 1 ? 'active' : '']"
                  @click="switchTab(1)">已提交({{ checkedCount }})
          </button>
        </view>
      </view>
    </view>
    <!-- å¤´éƒ¨ä¿¡æ¯ -->
<!--    <view class="header-section">
      <h1>产线提交</h1>
    </view> -->
    <!-- æ£€éªŒå•列表 -->
    <view class="inspection-list">
      <!-- æ£€éªŒå•卡片 -->
      <view v-for="(item, index) in data" :key="item.id" class="inspection-card">
        <view class="card-header">
          <!-- æ·»åŠ æ ‡è¯†badge -->
          <view v-if="item.urgent == 1" class="badge urgent">急料</view>
          <view v-if="item.isFirst == 1" class="badge normal">首次</view>
          <view v-if="currentTab === 1" class="card-title">检验单号: {{ item.billNo }}</view>
          <view v-if="currentTab === 0" class="card-title">工单号: {{ item.daA001 }}</view>
          <!-- æœªæäº¤é¡µé¢æ˜¾ç¤ºä¸åˆæ ¼çŠ¶æ€ -->
          <view v-if="currentTab === 0 && item.result === '不合格'" class="status status-fail-alert">
            ä¸åˆæ ¼
          </view>
          <!-- å·²æäº¤é¡µé¢æ˜¾ç¤ºæ£€éªŒçŠ¶æ€ -->
          <view v-if="currentTab === 1" :class="{
                  'status-pass': item.result === '合格',
                  'status-fail': item.result === '不合格',
                  'status-submitted': !item.result
                }"
                class="status">
            {{ item.result ? item.result : '已提交' }}
          </view>
        </view>
        <view class="card-body">
          <view class="info-row">
            <view class="info-item">
              <view class="info-label">物料信息</view>
              <view class="info-content">{{ item.itemNo }} | {{ item.daA003 }}<br>{{ item.daA004 }}</view>
            </view>
          </view>
          <view class="info-row">
            <view class="info-item">
              <view class="info-label">项目</view>
              <view class="info-content">{{ item.projecT_CODE }}</view>
            </view>
            <view class="info-item">
              <view class="info-label">开工状态</view>
              <view class="info-content">{{ item.daA018 }}</view>
            </view>
            <view class="info-item">
              <view class="info-label">齐套状态</view>
              <view class="info-content">{{ item.daA019 }}</view>
            </view>
          </view>
        <view class="info-row">
            <view class="info-item">
              <view class="info-label">产线</view>
              <view class="info-content">{{ item.line }}</view>
            </view>
            <view class="info-item">
              <view class="info-label">工单号</view>
              <view class="info-content">{{ item.daA001 }}</view>
            </view>
            <view class="info-item">
              <view class="info-label">工单数</view>
              <view class="info-content highlight">{{ item.daA008 }}</view>
            </view>
          </view>
          <view class="info-row">
          </view>
          <!-- å·²æäº¤çŠ¶æ€ä¸‹æ˜¾ç¤ºæ£€éªŒä¿¡æ¯ -->
          <view v-if="currentTab === 1" class="meta-info">
            <view class="meta-item">检验单号: {{ item.billNo }}</view>
          </view>
          <view   class="meta-info">
                      <view class="meta-item">检验人: {{ item.statusUser }}</view>
          </view>
          <view v-if="currentTab === 1" class="meta-info">
              <view class="meta-item">创建时间: {{ item.createTime }}</view>
            <view v-if="item.result" class="meta-item">检验状态: {{ item.result }}</view>
          </view>
        </view>
        <view class="card-actions">
          <button v-if="currentTab === 0" class="primary" @click="submitInspection(item, userId)">提交检验</button>
          <!-- <button v-if="currentTab === 1" class="secondary" @click="viewDetail(item)">查看详情</button> -->
        </view>
      </view>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {
      currentTab: 0, // 0: æœªæäº¤, 1: å·²æäº¤
      data: [],
      pageIndex: 1,
      limit: 20,
      totalPage: 0,
      totalCount: 0,
      noData: false,
      isLoading: false,
      tipShow: false,
      searchValue: '',
      userId: "",
      uncheckedCount: 0,
      checkedCount: 0
    };
  },
  // é¡µé¢åŠ è½½æ—¶åªæ‰§è¡Œä¸€æ¬¡
  async onLoad() {
    const user = this.$loginInfo;
    this.userId = user.account;
    console.log("用户ID =", this.userId);
    // åˆå§‹åŒ–加载数据
    await this.init();
  },
  methods: {
    // Tab切换
    async switchTab(tabIndex) {
      if (this.currentTab !== tabIndex) {
        this.currentTab = tabIndex;
        this.data = [];
        this.pageIndex = 1;
        await this.init();
      }
    },
    async init() {
      if (this.isLoading) return;
      this.isLoading = true;
      const userName = this.$loginInfo.account;
      const result = this.currentTab === 1 ? "已完成" : "未完成";
      try {
        const res = await this.$post({
          url: "/ProductionLine/GetProductionLinePage",  // äº§çº¿æäº¤æŽ¥å£
          data: {
            pageIndex: this.pageIndex,
            limit: this.limit,
            statusUser: userName,
            status: this.currentTab,  // 0: æœªæäº¤, 1: å·²æäº¤
            searchValue: this.searchValue
          }
        });
        let list = res.data.tbBillList || [];
        // å¦‚果是未提交页面,对不合格的数据进行排序置顶
        if (this.currentTab === 0 && list.length > 0) {
          // å°†ä¸åˆæ ¼çš„æ•°æ®ç½®é¡¶
          const failedItems = list.filter(item => item.result === '不合格');
          const otherItems = list.filter(item => item.result !== '不合格');
          list = [...failedItems, ...otherItems];
        }
        if (this.pageIndex === 1) {
          this.data = list;
        } else {
          this.data.push(...list);
        }
        this.totalCount = res.totalCount;
        this.totalPage = Math.ceil(this.totalCount / this.limit);
        this.noData = this.pageIndex >= this.totalPage;
        if (this.currentTab === 1) {
          this.checkedCount = this.totalCount;
        } else {
          this.uncheckedCount = this.totalCount;
        }
      } catch (e) {
        console.error("加载检验单数据失败:", e);
      } finally {
        this.isLoading = false;
      }
    },
    // æäº¤æ£€éªŒ
    async submitInspection(item, userId) {
      console.log("提交检验 - å·¥å•ID:", item.id, "用户账号:", userId);
      if (!userId) {
        this.$showMessage("用户账号不能为空");
        return;
      }
      uni.showLoading({
        title: '提交中...'
      });
      try {
        const res = await this.$post({
          url: "/ProductionLine/SubmitInspection",
          data: {
            userNo: userId,
            gid: item.id
          }
        });
        // æ£€æŸ¥å¤šç§æˆåŠŸæ¡ä»¶
        if (res.statusCode === 200 || res.status === 0 || res.data === true || res.data.tbBillList === true) {
          this.$showMessage("成功提交检验");
          // ä»Žåˆ—表中移除已提交的项
          this.data = this.data.filter(dataItem => dataItem.id !== item.id);
          this.uncheckedCount--;
          this.checkedCount++;
          // å¦‚果列表为空,刷新页面
          if (this.data.length === 0) {
            this.pageIndex = 1;
            await this.init();
          }
        } else {
          this.$showMessage(res.data.message || res.message || "提交失败");
        }
      } catch (err) {
        console.log("提交出错:", err);
        this.$showMessage("提交失败,请重试");
      } finally {
        uni.hideLoading();
      }
    },
    // æŸ¥çœ‹è¯¦æƒ…
    viewDetail(item) {
      uni.navigateTo({
        url: `Add?id=${item.id}&billNo=${item.billNo}&current=B`
      });
    }
  },
  // ä¸‹æ‹‰åˆ·æ–°
  onPullDownRefresh() {
    this.pageIndex = 1;
    this.init().then(() => {
      this.tipShow = true;
      uni.stopPullDownRefresh();
      setTimeout(() => (this.tipShow = false), 3000);
    });
  },
  // ä¸Šæ‹‰åŠ è½½æ›´å¤š
  onReachBottom() {
    if (this.noData || this.isLoading) return;
    this.pageIndex++;
    this.init();
  }
};
</script>
<style scoped>
/* åŸºç¡€æ ·å¼é‡ç½® */
.inspection-app {
  padding: 10px;
  background-color: #f5f7fa;
  min-height: 100vh;
}
/* é¡¶éƒ¨ç­›é€‰åŒº */
.filter-section {
  /* margin-bottom: 24px; */
}
.filter-section h1 {
  font-size: 24px;
  font-weight: 600;
  color: #2c3e50;
  margin-bottom: 16px;
}
/* æœç´¢æ¡†æ ·å¼ */
.search-container {
  display: flex;
  flex: 1;
  margin: 0 10px;
  height: 36px;
}
.search-input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px 0 0 4px;
  font-size: 14px;
  background-color: white;
}
.search-button {
  padding: 0 12px;
  border: 1px solid #3498db;
  border-radius: 0 4px 4px 0;
  background: linear-gradient(135deg, #3498db, #2980b9);
  color: white;
  font-size: 14px;
  margin: 0;
  cursor: pointer;
  transition: all 0.3s ease;
}
.search-button:hover {
  background: linear-gradient(135deg, #2980b9, #1f618d);
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);
}
.search-button:active {
  transform: translateY(0);
}
.filter-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.dropdown-filter {
  min-width: 70px;
}
.badge {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 12px;
  margin-right: 8px;
  font-weight: 500;
  letter-spacing: 0.5px;
}
.badge.urgent {
  background: linear-gradient(135deg, #e74c3c, #c0392b);
  color: white;
  box-shadow: 0 2px 4px rgba(231, 76, 60, 0.3);
}
.badge.normal {
  background: linear-gradient(135deg, #f39c12, #e67e22);
  color: white;
  box-shadow: 0 2px 4px rgba(243, 156, 18, 0.3);
}
.meta-info {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: #95a5a6;
  margin-top: 12px;
}
.meta-item {
  display: flex;
  align-items: center;
  gap: 4px;
}
.picker {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
  font-size: 14px;
  min-width: 120px;
}
.filter-label {
  font-size: 14px;
  color: #7f8c8d;
}
.status-tabs {
  display: flex;
  border-radius: 4px;
  overflow: hidden;
  background-color: #ecf0f1;
  flex: 1;
  min-width: 200px;
}
.tab-button {
  padding: 0px 16px;
  border: none;
  background: none;
  font-size: 14px;
  transition: all 0.3s;
  margin: 0;
  height: 35px;
}
.tab-button.active {
  background: linear-gradient(135deg, #3498db, #2980b9);
  color: white;
  box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);
}
/* æ£€éªŒå•列表 */
.inspection-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
/* æ£€éªŒå•卡片 */
.inspection-card {
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
  overflow: hidden;
  transition: all 0.3s ease;
  border: 1px solid rgba(52, 152, 219, 0.1);
}
.inspection-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  border-color: rgba(52, 152, 219, 0.3);
}
.card-header {
  padding: 16px;
  border-bottom: 1px solid #eee;
  display: flex;
  align-items: center;
  background: linear-gradient(135deg, #f8f9fa, #e9ecef);
}
.card-title {
  font-size: 16px;
  font-weight: 600;
  flex: 1;
  margin: 0 8px;
  color: #2c3e50;
}
.status {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 6px;
  font-weight: 500;
  letter-spacing: 0.3px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.status-pending {
  background: linear-gradient(135deg, #f39c12, #e67e22);
  color: white;
}
.status-assigned {
  background: linear-gradient(135deg, #3498db, #2980b9);
  color: white;
}
.status-pass {
  background: linear-gradient(135deg, #27ae60, #229954);
  color: white;
}
.status-fail {
  background: linear-gradient(135deg, #3498db, #2980b9);
  color: white;
}
.status-submitted {
  background: linear-gradient(135deg, #95a5a6, #7f8c8d);
  color: white;
}
.status-fail-alert {
  background: linear-gradient(135deg, #e74c3c, #c0392b);
  color: white;
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.7);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(231, 76, 60, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0);
  }
}
.card-body {
  padding: 16px;
}
.info-row {
  display: flex;
  margin-bottom: 12px;
  gap: 16px;
}
.info-item {
  flex: 1;
}
.info-label {
  display: block;
  font-size: 12px;
  color: #7f8c8d;
  margin-bottom: 4px;
}
.info-content {
  font-size: 14px;
  color: #2c3e50;
  line-height: 1.5;
}
.highlight {
  font-weight: 600;
  color: #e74c3c;
  font-size: 16px;
}
.card-actions {
  padding: 12px 16px;
  border-top: 1px solid #eee;
  display: flex;
  gap: 8px;
}
button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
  font-size: 14px;
  transition: all 0.2s;
  flex: 1;
}
button.primary {
  background: linear-gradient(135deg, #3498db, #2980b9);
  color: white;
  border-color: #2980b9;
  box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);
  transition: all 0.3s ease;
}
button.primary:hover {
  background: linear-gradient(135deg, #2980b9, #1f618d);
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(52, 152, 219, 0.4);
}
button.primary:active {
  transform: translateY(0);
}
button.secondary {
  background: linear-gradient(135deg, #95a5a6, #7f8c8d);
  color: white;
  border-color: #7f8c8d;
  box-shadow: 0 2px 4px rgba(149, 165, 166, 0.3);
  transition: all 0.3s ease;
}
button.secondary:hover {
  background: linear-gradient(135deg, #7f8c8d, #6c7b7d);
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(149, 165, 166, 0.4);
}
button.secondary:active {
  transform: translateY(0);
}
/* å“åº”式设计 */
@media (min-width: 768px) {
  .inspection-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
  }
  .info-row {
    flex-direction: row;
  }
}
/* å“åº”式设计 */
@media (min-width: 300px) {
  .inspection-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  }
  .info-row {
    flex-direction: row;
  }
  .picker {
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    background-color: white;
    font-size: 14px;
    min-width: 10px;
  }
}
/* åˆ·æ–°æç¤ºæ ·å¼ */
.tips {
  color: #67c23a;
  font-size: 14px;
  line-height: 40px;
  text-align: center;
  background-color: #f0f9eb;
  height: 0;
  opacity: 0;
  transform: translateY(-100%);
  transition: all 0.3s;
}
.tips-ani {
  transform: translateY(0);
  height: 40px;
  opacity: 1;
}
</style>