From 2dd434830299e781cd942ef5e6e938160dd12704 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 03 三月 2026 17:15:18 +0800
Subject: [PATCH] 原材料检验功能开发
---
src/pages/qualityManagement/materialInspection/index.vue | 814 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 814 insertions(+), 0 deletions(-)
diff --git a/src/pages/qualityManagement/materialInspection/index.vue b/src/pages/qualityManagement/materialInspection/index.vue
new file mode 100644
index 0000000..c575493
--- /dev/null
+++ b/src/pages/qualityManagement/materialInspection/index.vue
@@ -0,0 +1,814 @@
+<template>
+ <view class="material-inspection-page">
+ <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+ <PageHeader title="鍘熸潗鏂欐楠�"
+ @back="goBack" />
+ <!-- 鎼滅储鍖哄煙 -->
+ <view class="search-section">
+ <view class="search-bar">
+ <view class="search-input">
+ <up-input class="search-text"
+ placeholder="璇疯緭鍏ヤ緵搴斿晢鎼滅储"
+ v-model="searchForm.supplier"
+ @change="getList"
+ clearable />
+ </view>
+ <!-- <view class="filter-button"
+ @click="showDatePicker">
+ <up-icon name="calendar"
+ size="24"
+ color="#999"></up-icon>
+ </view> -->
+ <view class="filter-button"
+ @click="getList">
+ <up-icon name="search"
+ size="24"
+ color="#999"></up-icon>
+ </view>
+ </view>
+ <!-- 鏃ユ湡閫夋嫨 -->
+ <!-- <view class="date-range"
+ v-if="searchForm.entryDate">
+ <text class="date-text">{{ searchForm.entryDate[0] }} 鑷� {{ searchForm.entryDate[1] }}</text>
+ <up-icon name="close"
+ size="16"
+ color="#999"
+ @click="clearDateRange"></up-icon>
+ </view> -->
+ </view>
+ <!-- 缁熻淇℃伅鍗$墖 -->
+ <!-- <view class="stats-cards">
+ <view class="stat-card">
+ <text class="stat-number">{{ totalCount }}</text>
+ <text class="stat-label">鎬绘楠�</text>
+ </view>
+ <view class="stat-card">
+ <text class="stat-number">{{ submittedCount }}</text>
+ <text class="stat-label">宸叉彁浜�</text>
+ </view>
+ <view class="stat-card">
+ <text class="stat-number">{{ pendingCount }}</text>
+ <text class="stat-label">寰呮彁浜�</text>
+ </view>
+ <view class="stat-card">
+ <text class="stat-number">{{ qualifiedCount }}</text>
+ <text class="stat-label">宸插悎鏍�</text>
+ </view>
+ </view> -->
+ <!-- 妫�楠屽垪琛� -->
+ <view class="inspection-list"
+ v-if="inspectionList.length > 0">
+ <view v-for="(item, index) in inspectionList"
+ :key="index">
+ <view class="inspection-item"
+ @click="viewDetail(item)">
+ <view class="item-header">
+ <view class="item-left">
+ <!-- <view class="material-icon"
+ :class="getStateClass(item.inspectState)">
+ <up-icon :name="getStateIcon(item.inspectState)"
+ size="16"
+ color="#ffffff"></up-icon>
+ </view> -->
+ <view class="material-info">
+ <text class="material-name">{{ item.productName }}</text>
+ <text class="material-code">{{ item.model }}</text>
+ </view>
+ </view>
+ <view class="status-tags">
+ <u-tag :type="getTagType(item.checkResult)"
+ size="mini"
+ class="status-tag">
+ {{ item.checkResult }}
+ </u-tag>
+ <u-tag :type="getStateTagType(item.inspectState)"
+ size="mini"
+ class="status-tag">
+ {{ item.inspectState ? '宸叉彁浜�' : '鏈彁浜�' }}
+ </u-tag>
+ </view>
+ </view>
+ <up-divider></up-divider>
+ <view class="item-details">
+ <view class="detail-row">
+ <text class="detail-label">妫�娴嬫棩鏈�</text>
+ <text class="detail-value">{{ formatDateTime(item.checkTime) || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">閲囪喘璁㈠崟鍙�</text>
+ <text class="detail-value">{{ item.purchaseContractNo || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">渚涘簲鍟�</text>
+ <text class="detail-value">{{ item.supplier || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">妫�楠屽憳</text>
+ <text class="detail-value">{{ item.checkName || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鏁伴噺</text>
+ <text class="detail-value">{{ item.quantity || 0 }} {{ item.unit || '' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">妫�娴嬪崟浣�</text>
+ <text class="detail-value">{{ item.checkCompany || '-' }}</text>
+ </view>
+ </view>
+ <!-- 鎿嶄綔鎸夐挳 -->
+ <view class="action-buttons">
+ <u-button type="primary"
+ size="small"
+ class="action-btn"
+ :disabled="item.inspectState"
+ @click.stop="startInspection(item)">
+ 缂栬緫
+ </u-button>
+ <u-button type="info"
+ size="small"
+ class="action-btn"
+ @click.stop="viewDetail(item)">
+ 璇︽儏
+ </u-button>
+ <u-button type="success"
+ size="small"
+ class="action-btn"
+ :disabled="item.inspectState"
+ @click.stop="submitInspection(item)">
+ 鎻愪氦
+ </u-button>
+ </view>
+ <view class="action-buttons">
+ <u-button type="info"
+ size="small"
+ class="action-btn"
+ @click.stop="viewFileList(item)">
+ 闄勪欢
+ </u-button>
+ <u-button type="warning"
+ size="small"
+ class="action-btn"
+ :disabled="item.inspectState || item.checkName !== ''"
+ @click.stop="assignInspector(item)">
+ 鍒嗛厤妫�楠屽憳
+ </u-button>
+ </view>
+ </view>
+ </view>
+ </view>
+ <view v-else
+ class="no-data">
+ <up-empty mode="data"
+ text="鏆傛棤妫�楠屼换鍔�"></up-empty>
+ </view>
+ <!-- 鍒嗛〉缁勪欢 -->
+ <!-- 娴姩鏂板鎸夐挳 -->
+ <view class="fab-button"
+ @click="addInspection">
+ <up-icon name="plus"
+ size="24"
+ color="#ffffff"></up-icon>
+ </view>
+ <!-- 鏃ユ湡閫夋嫨鍣� -->
+ <up-popup v-model:show="showDate"
+ mode="date"
+ :start-year="2020"
+ :end-year="2030"
+ :range="true"
+ @confirm="confirmDate" />
+ <!-- 鍒嗛厤妫�楠屽憳寮圭獥 -->
+ <up-popup v-model:show="showAssignDialog"
+ mode="center"
+ round
+ style="width: 80%">
+ <view class="assign-dialog">
+ <view class="dialog-header">
+ <text class="dialog-title">鍒嗛厤妫�楠屽憳</text>
+ <up-icon name="close"
+ size="20"
+ color="#999"
+ @click="showAssignDialog = false"></up-icon>
+ </view>
+ <view class="dialog-content">
+ <up-form-item label="妫�楠屽憳"
+ prop="checkName"
+ :label-width="60"
+ required>
+ <up-input v-model="assignForm.checkName"
+ placeholder="璇烽�夋嫨妫�楠屽憳"
+ readonly />
+ <template #right>
+ <up-icon @click="showInspectorSheet = true"
+ name="arrow-right" />
+ </template>
+ </up-form-item>
+ </view>
+ <view class="dialog-footer">
+ <u-button type="default"
+ class="footer-btn"
+ @click="showAssignDialog = false">
+ 鍙栨秷
+ </u-button>
+ <u-button type="primary"
+ class="footer-btn"
+ @click="submitAssign">
+ 纭畾
+ </u-button>
+ </view>
+ </view>
+ </up-popup>
+ <!-- 妫�楠屽憳閫夋嫨 -->
+ <up-action-sheet :show="showInspectorSheet"
+ :actions="userSheetOptions"
+ @select="selectInspector"
+ title="閫夋嫨妫�楠屽憳" />
+ </view>
+</template>
+
+<script setup>
+ import { ref, computed, onMounted } from "vue";
+ import { onShow } from "@dcloudio/uni-app";
+ import PageHeader from "@/components/PageHeader.vue";
+ import dayjs from "dayjs";
+ import {
+ submitQualityInspect,
+ qualityInspectUpdate,
+ qualityInspectListPage,
+ } from "@/api/qualityManagement/materialInspection.js";
+ import { userListNoPage } from "@/api/system/user.js";
+
+ // 鏄剧ず鎻愮ず淇℃伅
+ const showToast = message => {
+ uni.showToast({
+ title: message,
+ icon: "none",
+ });
+ };
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = ref({
+ supplier: "",
+ entryDate: undefined,
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ });
+
+ // 鏃ユ湡閫夋嫨鍣�
+ const showDate = ref(false);
+
+ // 鍒嗛厤妫�楠屽憳寮圭獥
+ const showAssignDialog = ref(false);
+ const showInspectorSheet = ref(false);
+ const assignForm = ref({
+ checkName: "",
+ });
+ const currentAssignRow = ref(null);
+
+ // 妫�楠屽垪琛ㄦ暟鎹�
+ const inspectionList = ref([]);
+
+ // 鍒嗛〉鏁版嵁
+ const page = ref({
+ current: -1,
+ size: -1,
+ total: 0,
+ });
+
+ // 鍔犺浇鐘舵��
+ const tableLoading = ref(false);
+
+ // 缁熻鏁版嵁
+ const totalCount = ref(0);
+ const submittedCount = ref(0);
+ const pendingCount = ref(0);
+ const qualifiedCount = ref(0);
+
+ // 妫�楠屽憳鍒楄〃
+ const userList = ref([]);
+
+ // ActionSheet閫夐」
+ const userSheetOptions = computed(() => {
+ return userList.value.map(item => ({
+ name: item.nickName,
+ value: item.nickName,
+ }));
+ });
+
+ // 杩斿洖涓婁竴椤�
+ const goBack = () => {
+ uni.navigateBack();
+ };
+
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ const formatDateTime = dateStr => {
+ if (!dateStr) return "";
+ return dayjs(dateStr).format("YYYY-MM-DD");
+ };
+
+ // 鑾峰彇鐘舵�佹牱寮�
+ const getStateClass = inspectState => {
+ return inspectState ? "state-submitted" : "state-pending";
+ };
+
+ // 鑾峰彇鐘舵�佸浘鏍�
+ const getStateIcon = inspectState => {
+ return inspectState ? "checkmark-circle" : "time";
+ };
+
+ // 鑾峰彇鏍囩绫诲瀷
+ const getTagType = checkResult => {
+ if (checkResult === "鍚堟牸") return "success";
+ if (checkResult === "涓嶅悎鏍�") return "error";
+ return "default";
+ };
+
+ // 鑾峰彇鐘舵�佹爣绛剧被鍨�
+ const getStateTagType = inspectState => {
+ return inspectState ? "success" : "warning";
+ };
+
+ // 鏄剧ず鏃ユ湡閫夋嫨鍣�
+ const showDatePicker = () => {
+ showDate.value = true;
+ };
+
+ // 纭鏃ユ湡閫夋嫨
+ const confirmDate = e => {
+ searchForm.value.entryDate = e.value;
+ searchForm.value.entryDateStart = dayjs(e.value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(e.value[1]).format("YYYY-MM-DD");
+ getList();
+ };
+ const viewFileList = item => {
+ uni.setStorageSync("qualityInspectFileId", item.id);
+ uni.navigateTo({
+ url: "/pages/qualityManagement/materialInspection/fileList",
+ });
+ };
+
+ // 娓呴櫎鏃ユ湡鑼冨洿
+ const clearDateRange = () => {
+ searchForm.value.entryDate = undefined;
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ getList();
+ };
+
+ // 鑾峰彇鐢ㄦ埛鍒楄〃
+ const getUserList = async () => {
+ try {
+ const userRes = await userListNoPage();
+ userList.value = userRes.data || [];
+ } catch (e) {
+ console.error("鍔犺浇妫�楠屽憳鍒楄〃澶辫触", e);
+ userList.value = [];
+ }
+ };
+
+ // 鏌ヨ鍒楄〃
+ const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page.value };
+ params.entryDate = undefined;
+ qualityInspectListPage({ ...params, inspectType: 0 })
+ .then(res => {
+ tableLoading.value = false;
+ inspectionList.value = res.data.records || [];
+ page.value.total = res.data.total || 0;
+ totalCount.value = res.data.total || 0;
+ submittedCount.value = inspectionList.value.filter(
+ item => item.inspectState
+ ).length;
+ pendingCount.value = inspectionList.value.filter(
+ item => !item.inspectState
+ ).length;
+ qualifiedCount.value = inspectionList.value.filter(
+ item => item.checkResult === "鍚堟牸"
+ ).length;
+ })
+ .catch(err => {
+ tableLoading.value = false;
+ console.error("鑾峰彇鍒楄〃澶辫触:", err);
+ showToast("鑾峰彇鍒楄〃澶辫触锛岃閲嶈瘯");
+ });
+ };
+
+ // 缂栬緫妫�楠�
+ const startInspection = item => {
+ if (!item) {
+ showToast("鍙傛暟閿欒");
+ return;
+ }
+ // 瀛樺偍瀹屾暣鐨勬楠屾暟鎹�
+ uni.setStorageSync("inspectionEditData", item);
+ // 璺宠浆鍒扮紪杈戦〉闈�
+ uni.navigateTo({
+ url: `/pages/qualityManagement/materialInspection/add?id=${item.id}&isEdit=true`,
+ });
+ };
+
+ // 鏌ョ湅璇︽儏
+ const viewDetail = item => {
+ if (!item) {
+ showToast("鍙傛暟閿欒");
+ return;
+ }
+ // 璺宠浆鍒拌鎯呴〉闈�
+ uni.navigateTo({
+ url: `/pages/qualityManagement/materialInspection/detail?id=${item.id}`,
+ });
+ };
+
+ // 鏂板妫�楠�
+ const addInspection = () => {
+ uni.navigateTo({
+ url: "/pages/qualityManagement/materialInspection/add",
+ });
+ };
+
+ // 鎻愪氦妫�楠�
+ const submitInspection = async item => {
+ if (!item) {
+ showToast("鍙傛暟閿欒");
+ return;
+ }
+ try {
+ const res = await submitQualityInspect({ id: item.id });
+ if (res.code === 200) {
+ showToast("鎻愪氦鎴愬姛");
+ setTimeout(() => {
+ getList();
+ }, 1000);
+ } else {
+ showToast("鎻愪氦澶辫触锛�" + (res.msg || "鏈煡閿欒"));
+ }
+ } catch (error) {
+ console.error("鎻愪氦澶辫触:", error);
+ showToast("鎻愪氦澶辫触锛岃閲嶈瘯");
+ }
+ };
+
+ // 鍒嗛厤妫�楠屽憳
+ const assignInspector = item => {
+ if (!item) {
+ showToast("鍙傛暟閿欒");
+ return;
+ }
+ currentAssignRow.value = item;
+ getUserList();
+ showAssignDialog.value = true;
+ };
+
+ // 閫夋嫨妫�楠屽憳
+ const selectInspector = e => {
+ assignForm.value.checkName = e.value;
+ showInspectorSheet.value = false;
+ };
+
+ // 鎻愪氦鍒嗛厤
+ const submitAssign = async () => {
+ if (!currentAssignRow.value || !assignForm.value.checkName) {
+ showToast("璇烽�夋嫨妫�楠屽憳");
+ return;
+ }
+ try {
+ const data = {
+ ...assignForm.value,
+ id: currentAssignRow.value.id,
+ };
+ const res = await qualityInspectUpdate(data);
+ if (res.code === 200) {
+ showToast("鍒嗛厤鎴愬姛");
+ showAssignDialog.value = false;
+ setTimeout(() => {
+ getList();
+ }, 1000);
+ } else {
+ showToast("鍒嗛厤澶辫触锛�" + (res.msg || "鏈煡閿欒"));
+ }
+ } catch (error) {
+ console.error("鍒嗛厤澶辫触:", error);
+ showToast("鍒嗛厤澶辫触锛岃閲嶈瘯");
+ }
+ };
+
+ // 澶勭悊鍒嗛〉
+ const handlePagination = obj => {
+ page.value.current = obj.current;
+ page.value.size = obj.size;
+ getList();
+ };
+
+ onMounted(() => {
+ getList();
+ getUserList();
+ });
+
+ onShow(() => {
+ getList();
+ });
+</script>
+
+<style scoped lang="scss">
+ @import "../../../styles/sales-common.scss";
+
+ .material-inspection-page {
+ min-height: 100vh;
+ background: #f8f9fa;
+ padding-bottom: 80px;
+ }
+
+ // 鎼滅储鍖哄煙
+ .search-section {
+ padding: 10px 15px;
+ background: #fff;
+ border-bottom: 1px solid #f0f0f0;
+ }
+
+ .search-bar {
+ display: flex;
+ align-items: center;
+ background: #f8f9fa;
+ border-radius: 20px;
+ padding: 0 15px;
+ height: 40px;
+ }
+
+ .search-input {
+ flex: 1;
+ }
+
+ .search-text {
+ background: transparent;
+ border: none;
+ }
+
+ .filter-button {
+ margin-left: 10px;
+ padding: 5px;
+ }
+
+ // 缁熻鍗$墖
+ .stats-cards {
+ display: flex;
+ padding: 15px;
+ gap: 10px;
+ background: #fff;
+ margin-bottom: 10px;
+ }
+
+ .stat-card {
+ flex: 1;
+ background: #2979ff;
+ border-radius: 12px;
+ padding: 15px;
+ text-align: center;
+ color: #fff;
+ box-shadow: 0 2px 8px rgba(41, 121, 255, 0.2);
+ }
+
+ .stat-number {
+ display: block;
+ font-size: 20px;
+ font-weight: 600;
+ margin-bottom: 5px;
+ }
+
+ .stat-label {
+ font-size: 12px;
+ opacity: 0.9;
+ }
+
+ // 妫�楠屽垪琛�
+ .inspection-list {
+ padding: 20px;
+ }
+
+ .inspection-item {
+ background: #ffffff;
+ border-radius: 12px;
+ margin-bottom: 16px;
+ overflow: hidden;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+ padding: 0 16px;
+
+ &:active {
+ transform: scale(0.98);
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
+ }
+ }
+
+ .item-header {
+ padding: 16px 0;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ .item-left {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .material-icon {
+ width: 24px;
+ height: 24px;
+ background: #2979ff;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .state-pending {
+ background: #ff9900;
+ }
+
+ .state-submitted {
+ background: #52c41a;
+ }
+
+ .material-info {
+ flex: 1;
+ }
+
+ .material-name {
+ font-size: 14px;
+ color: #333;
+ font-weight: 500;
+ }
+
+ .material-code {
+ font-size: 12px;
+ color: #999;
+ margin-left: 8px;
+ }
+
+ .status-tags {
+ display: flex;
+ gap: 8px;
+ }
+
+ .status-tag {
+ margin: 0;
+ }
+
+ .date-range {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 10px;
+ padding: 8px 12px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ }
+
+ .date-text {
+ font-size: 12px;
+ color: #666;
+ }
+
+ // 璇︽儏琛�
+ .item-details {
+ padding: 16px 0;
+ }
+
+ .detail-row {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-bottom: 8px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .detail-label {
+ font-size: 12px;
+ color: #777777;
+ min-width: 60px;
+ }
+
+ .detail-value {
+ font-size: 12px;
+ color: #000000;
+ text-align: right;
+ flex: 1;
+ margin-left: 16px;
+ }
+
+ // 鎿嶄綔鎸夐挳
+ .action-buttons {
+ display: flex;
+ gap: 12px;
+ padding: 0 0 16px 0;
+ justify-content: space-between;
+ }
+
+ .action-btn {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ }
+
+ // 绌虹姸鎬�
+ .no-data {
+ padding: 60px 20px;
+ text-align: center;
+ }
+
+ // 娴姩鎸夐挳
+ .fab-button {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ width: 56px;
+ height: 56px;
+ background: #2979ff;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3);
+ z-index: 1000;
+ }
+
+ // 鍒嗛厤妫�楠屽憳寮圭獥
+ .assign-dialog {
+ padding: 24px;
+ background: #ffffff;
+ border-radius: 12px;
+ }
+
+ .dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid #f0f0f0;
+ }
+
+ .dialog-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .dialog-content {
+ margin-bottom: 24px;
+ }
+
+ .dialog-footer {
+ display: flex;
+ gap: 16px;
+ padding-top: 16px;
+ border-top: 1px solid #f0f0f0;
+ }
+
+ .footer-btn {
+ flex: 1;
+ height: 44px;
+ font-size: 16px;
+ }
+
+ // 杈撳叆妗嗘牱寮�
+ :deep(.up-input__inner) {
+ border-radius: 8px;
+ height: 44px;
+ font-size: 14px;
+ }
+
+ // 琛ㄥ崟椤规牱寮�
+ :deep(.up-form-item) {
+ margin-bottom: 0;
+ }
+
+ :deep(.up-form-item__label) {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 8px;
+ }
+
+ // 鎸夐挳鏍峰紡
+ :deep(.up-button--primary) {
+ border-radius: 8px;
+ }
+
+ :deep(.up-button--default) {
+ border-radius: 8px;
+ }
+
+ // 鍒嗛〉缁勪欢
+ .pagination {
+ padding: 20px;
+ background: #fff;
+ margin-top: 10px;
+ display: flex;
+ justify-content: center;
+ }
+</style>
--
Gitblit v1.9.3