From 2291b7406cdc184abfa1b1986baeb55499771343 Mon Sep 17 00:00:00 2001
From: ZN <zhang_12370@163.com>
Date: 星期一, 16 三月 2026 17:07:15 +0800
Subject: [PATCH] fix(设备管理): 修正添加维护接口的URL路径

---
 src/pages/consumablesLogistics/dispatchLog/index.vue |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/src/pages/consumablesLogistics/dispatchLog/index.vue b/src/pages/consumablesLogistics/dispatchLog/index.vue
new file mode 100644
index 0000000..132494f
--- /dev/null
+++ b/src/pages/consumablesLogistics/dispatchLog/index.vue
@@ -0,0 +1,223 @@
+<template>
+  <view class="dispatch-page">
+    <PageHeader title="鍑哄簱鍙拌处" @back="goBack" />
+    <view class="tabs-wrap">
+      <view
+        v-for="tab in tabs"
+        :key="tab.name"
+        class="tab-item"
+        :class="{ active: activeTab === tab.name }"
+        @click="activeTab = tab.name"
+      >
+        <text>{{ tab.label }}</text>
+      </view>
+    </view>
+    <view class="search-section">
+      <view class="search-row">
+        <view class="search-input-wrap">
+          <up-input v-model="searchForm.productName" placeholder="浜у搧澶х被" clearable />
+        </view>
+        <view class="btn-search" @click="handleQuery">
+          <view class="btn-search-inner">
+            <up-icon name="search" size="22" color="#fff"></up-icon>
+            <text>鎼滅储</text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="list-section">
+      <view v-if="tableData.length > 0">
+        <view v-for="(item, index) in tableData" :key="item.id || index" class="card-item">
+          <view class="card-click" @click="goDetail(item)">
+            <view class="card-header">
+              <view class="header-main">
+                <text class="product-name">{{ item.productName }}</text>
+                <text class="outbound-date">{{ item.createTime }}</text>
+              </view>
+            </view>
+            <up-divider />
+            <view class="card-body">
+              <view class="row"><text class="l">瑙勬牸鍨嬪彿</text><text class="r">{{ item.model }}</text></view>
+              <view class="row"><text class="l">鍗曚綅</text><text class="r">{{ item.unit }}</text></view>
+              <view class="row"><text class="l">鍑哄簱鏁伴噺</text><text class="r highlight">{{ item.stockOutNum }}</text></view>
+              <view class="row"><text class="l">鍑哄簱浜�</text><text class="r">{{ item.createBy }}</text></view>
+              <view class="row" v-if="item.recordType !== undefined"><text class="l">鏉ユ簮</text><text class="r">{{ getRecordType(item.recordType) || item.recordType }}</text></view>
+              <view class="row"><text class="l">姣涢噸(鍚�)</text><text class="r">{{ item.grossWeight ?? '-' }}</text></view>
+              <view class="row"><text class="l">鐨噸(鍚�)</text><text class="r">{{ item.tareWeight ?? '-' }}</text></view>
+              <view class="row"><text class="l">鍑�閲�(鍚�)</text><text class="r">{{ item.netWeight ?? '-' }}</text></view>
+              <view class="row"><text class="l">杩囩鏃ユ湡</text><text class="r">{{ item.weighingDate || '-' }}</text></view>
+              <view class="row"><text class="l">杩囩鍛�</text><text class="r">{{ item.weighingOperator || '-' }}</text></view>
+            </view>
+          </view>
+          <view class="card-actions">
+            <view class="btn-delete" @click.stop="handleDeleteSingle(item)">鍒犻櫎</view>
+          </view>
+        </view>
+      </view>
+      <view v-else class="no-data">鏆傛棤鏁版嵁</view>
+    </view>
+    <view class="load-more-wrap" v-if="tableData.length > 0">
+      <u-loadmore :status="loadStatus" @loadmore="loadMore" />
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { reactive, ref, toRefs, watch } from "vue";
+import { onReachBottom, onShow } from "@dcloudio/uni-app";
+import PageHeader from "@/components/PageHeader.vue";
+import { getConsumablesOutRecordPage, delConsumablesOutRecord } from "@/api/consumablesLogistics/consumablesOutRecord.js";
+import { findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions } from "@/api/basicData/enum.js";
+
+const activeTab = ref("qualified");
+const stockRecordTypeOptions = ref([]);
+const tabs = [
+  { label: "鍚堟牸鍑哄簱", name: "qualified", type: "0" },
+  { label: "涓嶅悎鏍煎嚭搴�", name: "unqualified", type: "1" },
+];
+const tableData = ref([]);
+const total = ref(0);
+const loadStatus = ref("loadmore");
+const page = reactive({ current: 1, size: 20 });
+const data = reactive({ searchForm: { productName: "" } });
+const { searchForm } = toRefs(data);
+
+const currentType = () => tabs.find((t) => t.name === activeTab.value)?.type || "0";
+
+function getRecordType(recordType) {
+  if (recordType == null || recordType === "") return "";
+  return stockRecordTypeOptions.value.find((item) => item.value === recordType)?.label || "";
+}
+
+function fetchRecordTypeOptions() {
+  const api =
+    currentType() === "1"
+      ? findAllUnQualifiedStockOutRecordTypeOptions
+      : findAllQualifiedStockOutRecordTypeOptions;
+  api()
+    .then((res) => {
+      const list = res.data != null ? res.data : res;
+      stockRecordTypeOptions.value = Array.isArray(list) ? list : [];
+    })
+    .catch(() => {
+      stockRecordTypeOptions.value = [];
+    });
+}
+
+const getList = () => {
+  const isFirstPage = page.current === 1;
+  if (isFirstPage) {
+    uni.showLoading({ title: "鍔犺浇涓�...", mask: true });
+  }
+  getConsumablesOutRecordPage({
+    ...page,
+    type: currentType(),
+    productName: searchForm.value.productName,
+  })
+    .then((res) => {
+      uni.hideLoading();
+      const records = res.data?.records || [];
+      const totalCount = res.data?.total || 0;
+      if (isFirstPage) {
+        tableData.value = records;
+        fetchRecordTypeOptions();
+      } else {
+        tableData.value = [...tableData.value, ...records];
+      }
+      total.value = totalCount;
+      loadStatus.value = tableData.value.length >= totalCount || totalCount === 0 ? "nomore" : "loadmore";
+    })
+    .catch(() => {
+      uni.hideLoading();
+      loadStatus.value = "error";
+      if (isFirstPage) {
+        uni.showToast({ title: "鍔犺浇澶辫触", icon: "none" });
+      }
+    });
+};
+
+const loadMore = () => {
+  if (loadStatus.value === "nomore" || loadStatus.value === "loading") return;
+  loadStatus.value = "loading";
+  page.current++;
+  getList();
+};
+
+watch(activeTab, () => {
+  page.current = 1;
+  loadStatus.value = "loadmore";
+  stockRecordTypeOptions.value = [];
+  getList();
+});
+
+const handleQuery = () => {
+  page.current = 1;
+  loadStatus.value = "loadmore";
+  getList();
+};
+
+const goDetail = (item) => {
+  if (!item?.id) return;
+  try {
+    uni.setStorageSync(
+      "dispatchDetailItem",
+      JSON.stringify({
+        item,
+        type: currentType(),
+      })
+    );
+  } catch (e) {}
+  uni.navigateTo({
+    url: "/pages/consumablesLogistics/dispatchLog/view?id=" + item.id,
+  });
+};
+
+const handleDeleteSingle = (item) => {
+  if (!item?.id) return;
+  uni.showModal({
+    title: "鍒犻櫎",
+    content: "纭鍒犻櫎璇ユ潯鍑哄簱璁板綍锛�",
+    success: (res) => {
+      if (!res.confirm) return;
+      delConsumablesOutRecord([item.id])
+        .then(() => {
+          uni.showToast({ title: "鍒犻櫎鎴愬姛", icon: "success" });
+          getList();
+        })
+        .catch(() => {
+          uni.showToast({ title: "鍒犻櫎澶辫触", icon: "none" });
+        });
+    },
+  });
+};
+
+const goBack = () => uni.navigateBack();
+onShow(() => getList());
+onReachBottom(() => loadMore());
+</script>
+
+<style lang="scss" scoped>
+.dispatch-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 40rpx; }
+.tabs-wrap { display: flex; background: #fff; padding: 24rpx; gap: 24rpx; }
+.tab-item { flex: 1; text-align: center; padding: 20rpx; border-radius: 12rpx; background: #f0f0f0; font-size: 28rpx; color: #666; }
+.tab-item.active { background: #2979ff; color: #fff; }
+.search-section { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; }
+.search-row { display: flex; align-items: center; }
+.search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
+.btn-search { display: flex; align-items: center; justify-content: center; width: 160rpx; min-height: 72rpx; flex-shrink: 0; padding: 20rpx 24rpx; background: #2979ff; color: #fff; border-radius: 12rpx; font-size: 28rpx; box-sizing: border-box; text-align: center; }
+.btn-search-inner { display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 8rpx; }
+.list-section { margin: 24rpx; }
+.card-item { background: #fff; border-radius: 16rpx; padding: 20rpx 24rpx; margin-bottom: 20rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.card-header { padding: 4rpx 0 12rpx; }
+.header-main { display: flex; justify-content: space-between; gap: 16rpx; }
+.product-name { font-size: 30rpx; font-weight: 500; color: #333; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.outbound-date { font-size: 24rpx; color: #999; }
+.card-body .row { display: flex; justify-content: space-between; padding: 6rpx 0; font-size: 26rpx; }
+.card-body .l { color: #666; }
+.card-body .r { color: #333; }
+.card-body .r.highlight { color: #2979ff; font-weight: 500; }
+.card-actions { display: flex; justify-content: flex-end; margin-top: 12rpx; }
+.btn-delete { color: #f56c6c; font-size: 28rpx; }
+.no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
+.load-more-wrap { padding: 24rpx 24rpx 8rpx; }
+</style>

--
Gitblit v1.9.3