spring
2025-11-19 8cc901ed214f3885b34a07d0520fbcfd50063439
src/pages/production/twist/selfInspect/index.vue
@@ -1,109 +1,697 @@
<template>
  <view class="list">
    <z-paging ref="pagingRef" v-model="cardList" :fixed="false" @query="getList">
      <template #top>
        <CardTitle title="绞线自检" :hideAction="false" />
      </template>
      <wd-card v-for="(item, index) in cardList" :key="index" type="rectangle" custom-class="round">
        <template #title>
          <view class="flex justify-between">
            <view>
              <wd-icon name="a-rootlist" color="#0D867F"></wd-icon>
              <text class="text-[#252525] ml-2 font-medium">{{ item.inspectionProject }}</text>
            </view>
            <view class="text-[#A8A8A8]" @click="toEdit">编辑</view>
          </view>
        </template>
        <ProductionCard :data="cardAttr" :value="item" color="#0D867F" />
      </wd-card>
    </z-paging>
    <wd-popup v-model="dialog.visible" position="bottom" custom-class="yl-popup">
      <view class="action px-3">
        <wd-button type="text" @click="cancel">取消</wd-button>
        <wd-button type="text" @click="submit">确定</wd-button>
    <!-- 基本信息模块 -->
    <wd-row>
      <view style="margin: 10rpx" class="flex justify-between items-center">
        <text class="title">基本信息</text>
        <view class="flex gap-2">
          <wd-button v-if="!isEdit" type="primary" size="small" icon="edit" @click="handleEdit">
            编辑
          </wd-button>
          <wd-button v-if="isEdit" type="info" size="small" icon="close" @click="handleCancel">
            取消
          </wd-button>
          <wd-button v-if="isEdit" type="success" size="small" icon="check" @click="handleSave">
            保存
          </wd-button>
        </view>
      </view>
      <SelfInspectForm />
      <wd-col :span="24">
        <wd-form-item label="日期" prop="recordDate">
          {{ formatDate(formData.recordDate) }}
        </wd-form-item>
        <wd-form-item label="机台" prop="deviceModel">
          {{ formatValue(formData.deviceModel) }}
        </wd-form-item>
        <wd-form-item label="班次" prop="workShift">
          {{ formatValue(formData.workShift) }}
        </wd-form-item>
        <wd-form-item label="产品类别" prop="productType">
          {{ formatValue(formData.productType) }}
        </wd-form-item>
        <wd-form-item label="型号规格" prop="model">
          {{ formatValue(formData.model) }}
        </wd-form-item>
        <wd-form-item label="生产长度" prop="actuallyLength">
          {{ formatValue(formData.actuallyLength, "m") }}
        </wd-form-item>
        <wd-form-item label="成品线盘号" prop="systemNo">
          {{ formatValue(formData.systemNo) }}
        </wd-form-item>
        <wd-form-item label="张力设置" prop="tensionSetting">
          <template v-if="isEdit">
            <wd-input v-model="formData.tensionSetting" placeholder="请输入张力设置" clearable />
          </template>
          <template v-else>
            {{ formatValue(formData.tensionSetting, "") }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 工艺记录模块 -->
    <wd-row>
      <view style="margin: 10rpx" class="flex justify-between items-center">
        <text class="title">工艺记录</text>
        <wd-button
          v-if="!isEdit"
          type="primary"
          size="small"
          icon="file-add"
          @click="handleAddInspection"
        >
          添加自检
        </wd-button>
      </view>
      <wd-col :span="24">
        <wd-card
          v-for="(item, index) in inspectionList"
          :key="index"
          type="rectangle"
          custom-class="round"
          style="margin-bottom: 12px"
        >
          <template #title>
            <view class="flex justify-between">
              <view>
                <text class="text-[#252525] font-medium">
                  记录位置:
                  {{
                    getRecordPositionLabel(
                      item.recordPosition || item.structureRecordResult?.recordPosition
                    )
                  }}
                </text>
              </view>
            </view>
          </template>
          <view class="px-3 pb-3">
            <view class="flex mb-2">
              <text class="text-[#646874] mr-3">成品结构:</text>
              <text class="text-[#252525]">
                {{
                  item.structureRecordResult?.inspectStructure?.structureFormula ||
                  item.structureFormula ||
                  "-"
                }}
              </text>
            </view>
            <view class="flex mb-2">
              <text class="text-[#646874] mr-3">成品外观:</text>
              <text class="text-[#252525]">
                {{
                  getAppearanceLabel(
                    item.structureRecordResult?.productAppearance || item.productAppearance
                  )
                }}
              </text>
            </view>
            <view class="flex mb-2">
              <text class="text-[#646874] mr-3">结论:</text>
              <text
                class="text-[#252525]"
                :style="{
                  color:
                    (item.structureRecordResult?.conclusion || item.conclusion) === '合格'
                      ? '#67C23A'
                      : '#F56C6C',
                }"
              >
                {{ item.structureRecordResult?.conclusion || item.conclusion || "-" }}
              </text>
            </view>
            <view class="flex">
              <text class="text-[#646874] mr-3">记录人:</text>
              <text class="text-[#252525]">{{ item.createUserName || "-" }}</text>
            </view>
          </view>
          <template #footer>
            <view class="flex justify-end gap-2">
              <wd-button size="small" plain @click="handleViewInspection(item, index)">
                查看
              </wd-button>
              <wd-button
                v-if="!isEdit"
                size="small"
                plain
                type="primary"
                @click="handleEditInspection(item, index)"
              >
                修改
              </wd-button>
              <wd-button
                v-if="!isEdit"
                size="small"
                plain
                type="error"
                @click="handleDeleteInspection(index)"
              >
                删除
              </wd-button>
            </view>
          </template>
        </wd-card>
        <view v-if="inspectionList.length === 0" class="text-center py-10 text-[#999]">
          暂无工艺记录
        </view>
      </wd-col>
    </wd-row>
    <!-- 自检弹窗 -->
    <wd-popup
      v-model="inspectionDialogVisible"
      position="bottom"
      custom-class="yl-popup"
      :close-on-click-modal="false"
    >
      <view class="action px-3">
        <wd-button type="text" @click="inspectionDialogVisible = false">取消</wd-button>
        <wd-button v-if="!isViewMode" type="text" @click="handleSaveInspection">保存</wd-button>
      </view>
      <SelfInspectForm
        ref="inspectionFormRef"
        :form-data="inspectionForm"
        :structure-items="structureItems"
        :twist-items="twistItems"
        :is-view-mode="isViewMode"
        :record-location="recordLocation"
        :appearance-options="appearanceOptions"
        @update:form-data="(val) => Object.assign(inspectionForm, val)"
        @update:structure-items="(val) => (structureItems = val)"
        @update:twist-items="(val) => (twistItems = val)"
      />
    </wd-popup>
    <wd-toast />
  </view>
</template>
<script setup lang="ts">
import CardTitle from "@/components/card-title/index.vue";
import ProductionCard from "../../components/ProductionCard.vue";
import { useToast } from "wot-design-uni";
import SelfInspectForm from "./form.vue";
import TwistApi from "@/api/product/twist";
import ManageApi from "@/api/product/manage";
import { onLoad } from "@dcloudio/uni-app";
import { ref, reactive } from "vue";
const pagingRef = ref();
const paramsId = ref();
const paramsId = ref<string | number>("");
const toast = useToast();
const dialog = reactive({
  visible: false,
const isEdit = ref(false);
const isViewMode = ref(false);
const loading = ref(false);
// 基本信息表单数据
const formData = reactive({
  id: undefined as number | string | undefined,
  recordDate: "",
  deviceModel: "",
  workShift: "",
  productType: "",
  model: "",
  actuallyLength: "",
  systemNo: "",
  tensionSetting: "",
  createUserName: "",
});
const cardAttr = ref<any[]>([
  {
    label: "单位",
    prop: "inspectionUnit",
  },
  {
    label: "标准值",
    prop: "standardValue",
  },
  {
    label: "自检值",
    prop: "inspectionItem",
  },
  {
    label: "自检结果",
    prop: "inspectionResult",
    color: "#FF1E1E",
  },
]);
const cardList = ref<any[]>([]);
// const addReport = () => {
//   dialog.visible = true;
// };
// 工艺记录列表
const inspectionList = ref<any[]>([]);
const toEdit = () => {
  uni.navigateTo({
    url: "/pages/production/twist/selfInspect/edit",
// 自检弹窗
const inspectionDialogVisible = ref(false);
const inspectionFormRef = ref();
const currentEditIndex = ref(-1);
// 自检表单数据
const inspectionForm = reactive({
  recordPosition: "",
  structureFormula: "",
  productAppearance: ["无外观问题"],
  conclusion: "合格",
  createUserName: "",
  twistedOuterDiameter: "",
});
// 结构检查数据
const structureItems = ref<any[]>([]);
// 绞线工艺数据
const twistItems = ref<any[]>([]);
// 存储从接口获取的结构公式
const structureFormulaFromApi = ref("");
// 字典数据
const recordLocation = ref<any>([]);
const appearanceOptions = ref<Array<{ label: string; value: string }>>([]);
// 获取外观标签
const getAppearanceLabel = (value: string | string[]) => {
  if (Array.isArray(value)) {
    return value.join("、") || "无";
  } else {
    return value || "无";
  }
};
// 获取记录位置标签
const getRecordPositionLabel = (value: string) => {
  const option = recordLocation.value.find((item: any) => item.value === value);
  return option ? option.label : value || "-";
};
// 格式化数值显示
const formatValue = (value: any, unit?: string) => {
  if (value === null || value === undefined || value === "") return "-";
  return unit ? `${value}${unit}` : value;
};
// 格式化日期显示
const formatDate = (date: string) => {
  if (!date) return "-";
  return new Date(date).toLocaleDateString("zh-CN", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  });
};
const submit = () => {
  toast.show("提交");
  dialog.visible = false;
// 计算节径比
const calculatePitchRatio = (pitch: string, dia: string) => {
  if (!pitch || !dia) return "-";
  const pitchNum = parseFloat(pitch);
  const diaNum = parseFloat(dia);
  if (isNaN(pitchNum) || isNaN(diaNum) || diaNum === 0) return "-";
  return (pitchNum / diaNum).toFixed(2);
};
const cancel = () => {
  toast.show("取消");
  dialog.visible = false;
// 初始化数据
const getData = async () => {
  if (!paramsId.value) {
    console.warn("wireId 不存在");
    return;
  }
  loading.value = true;
  try {
    // 获取基本信息
    const { code, data } = await TwistApi.getStrandedWireInspectionRecordStyleByWireId({
      wireId: paramsId.value,
    });
    if (code === 200 && data) {
      // 回显数据到表单
      if (data.fixedInfo) {
        Object.assign(formData, data.fixedInfo);
      }
      if (data.tensionSetting !== undefined) {
        formData.tensionSetting = data.tensionSetting;
      }
      // 处理结构检查数据
      if (data.inspectStructure) {
        if (data.inspectStructure.structureFormula) {
          structureFormulaFromApi.value = data.inspectStructure.structureFormula;
          inspectionForm.structureFormula = data.inspectStructure.structureFormula;
        }
        if (data.inspectStructure.structureItems) {
          structureItems.value = data.inspectStructure.structureItems.map((item: any) => ({
            ...item,
            actualValue1: "",
            actualValue2: "",
          }));
        }
      }
      // 处理绞线工艺数据
      if (data.inspectTwist) {
        twistItems.value = data.inspectTwist.map((item: any) => ({
          ...item,
          pitch: "",
        }));
      }
    }
    // 获取自检列表数据
    await getInspectionList();
    // 获取字典数据
    await loadDictData();
  } catch (error) {
    console.error("获取自检数据失败:", error);
    toast.error("获取自检数据失败");
  } finally {
    loading.value = false;
  }
};
const getList = async () => {
  const { data } = await ManageApi.getSelfInspection({
    outPutId: paramsId.value,
    type: "绞线",
// 获取自检列表数据
const getInspectionList = async () => {
  if (!paramsId.value) {
    console.warn("wireId 不存在");
    return;
  }
  try {
    const { code, data } = await TwistApi.getStrandedInspectionInfoByWireId({
      wireId: paramsId.value,
    });
    if (code === 200 && data) {
      inspectionList.value = data.structureInfos || [];
      inspectionList.value = inspectionList.value.map((item: any) => {
        return {
          ...item.structureRecordResult,
          ...item,
          structureFormula:
            item.structureRecordResult?.inspectStructure?.structureFormula || item.structureFormula,
        };
      });
    }
  } catch (error) {
    console.error("获取自检列表失败:", error);
  }
};
// 加载字典数据
const loadDictData = async () => {
  try {
    // 记录位置字典
    const recordLocationRes = await ManageApi.dictAPI("record_location");
    if (recordLocationRes.data && Array.isArray(recordLocationRes.data)) {
      recordLocation.value = recordLocationRes.data.map((item: any) => ({
        label: item.dictLabel || "",
        value: item.dictValue || "",
      }));
    }
    // 外观选项字典
    const appearanceRes = await ManageApi.dictAPI("draw_appearance_quality");
    if (appearanceRes.data && Array.isArray(appearanceRes.data)) {
      appearanceOptions.value = appearanceRes.data.map((item: any) => ({
        label: item.dictLabel || "",
        value: item.dictValue || "",
      }));
    }
  } catch (error) {
    console.error("加载字典数据失败:", error);
  }
};
// 保存基本信息
const handleSave = async () => {
  if (!formData.tensionSetting) {
    toast.warning("请输入张力设置");
    return;
  }
  try {
    const submitData = {
      wireId: paramsId.value,
      strandedWireInspectionRecordId: formData.id,
      tensionSetting: formData.tensionSetting,
    };
    const { code } = await TwistApi.saveStrandedWireInspectionFixedRecord(submitData);
    if (code === 200) {
      toast.success("保存成功");
      isEdit.value = false;
      await getData();
    } else {
      toast.error("保存失败");
    }
  } catch (error) {
    console.error("保存失败:", error);
    toast.error("保存失败");
  }
};
// 编辑
const handleEdit = () => {
  isEdit.value = true;
};
// 取消
const handleCancel = () => {
  isEdit.value = false;
  getData();
};
// 添加自检
const handleAddInspection = () => {
  currentEditIndex.value = -1;
  isViewMode.value = false;
  // 清空表单
  Object.assign(inspectionForm, {
    recordPosition: "",
    structureFormula: structureFormulaFromApi.value || "",
    productAppearance: ["无外观问题"],
    conclusion: "合格",
    createUserName: "",
    twistedOuterDiameter: "",
  });
  pagingRef.value.complete(data);
  // 重置结构项和绞线工艺数据
  if (structureItems.value.length > 0) {
    structureItems.value = structureItems.value.map((item: any) => {
      let defaultActualValue1 = "";
      if (item.structureValue && typeof item.structureValue === "string") {
        const parts = item.structureValue.split("/");
        if (parts.length > 0 && parts[0].trim()) {
          defaultActualValue1 = parts[0].trim();
        }
      }
      return {
        ...item,
        actualValue1: defaultActualValue1,
        actualValue2: "",
      };
    });
  }
  if (twistItems.value.length > 0) {
    twistItems.value = twistItems.value.map((item: any) => ({
      ...item,
      direction: item.direction || "",
      pitch: "",
    }));
  }
  inspectionDialogVisible.value = true;
};
onLoad((options: any) => {
// 编辑自检
const handleEditInspection = (row: any, index: number) => {
  currentEditIndex.value = index;
  isViewMode.value = false;
  const recordResult = row.structureRecordResult || {};
  const inspectStructure = recordResult.inspectStructure || row.inspectStructure || {};
  const inspectTwist = recordResult.inspectTwist || row.inspectTwist || [];
  // 重组表单数据
  Object.assign(inspectionForm, {
    recordPosition: recordResult.recordPosition || row.recordPosition || "",
    structureFormula: inspectStructure.structureFormula || row.structureFormula || "",
    productAppearance: recordResult.productAppearance || row.productAppearance || ["无外观问题"],
    conclusion: recordResult.conclusion || row.conclusion || "合格",
    twistedOuterDiameter:
      recordResult.twistedOuterDiameter ||
      inspectStructure.twistedOuterDiameter ||
      row.twistedOuterDiameter ||
      "",
    createUserName: row.createUserName || "",
  });
  // 重组结构项数据
  if (inspectStructure.structureItems) {
    structureItems.value = inspectStructure.structureItems.map((item: any) => ({
      ...item,
      actualValue1: item.actualValue1 || "",
      actualValue2: item.actualValue2 || "",
    }));
  }
  // 重组绞线工艺数据
  if (inspectTwist.length > 0) {
    twistItems.value = inspectTwist.map((item: any) => ({
      ...item,
      direction: item.direction || "",
      pitch: item.pitch || "",
      dia: item.dia || "",
      pitchRatio: item.pitchRatio || calculatePitchRatio(item.pitch, item.dia),
    }));
  }
  inspectionDialogVisible.value = true;
};
// 查看自检
const handleViewInspection = (row: any, index: number) => {
  currentEditIndex.value = index;
  isViewMode.value = true;
  const recordResult = row.structureRecordResult || {};
  const inspectStructure = recordResult.inspectStructure || row.inspectStructure || {};
  const inspectTwist = recordResult.inspectTwist || row.inspectTwist || [];
  Object.assign(inspectionForm, {
    recordPosition: recordResult.recordPosition || row.recordPosition || "",
    structureFormula: inspectStructure.structureFormula || row.structureFormula || "",
    productAppearance: recordResult.productAppearance || row.productAppearance || [],
    conclusion: recordResult.conclusion || row.conclusion || "合格",
    twistedOuterDiameter:
      recordResult.twistedOuterDiameter ||
      inspectStructure.twistedOuterDiameter ||
      row.twistedOuterDiameter ||
      "",
    createUserName: row.createUserName || "",
  });
  if (inspectStructure.structureItems) {
    structureItems.value = inspectStructure.structureItems.map((item: any) => ({
      ...item,
      actualValue1: item.actualValue1 || "",
      actualValue2: item.actualValue2 || "",
    }));
  }
  if (inspectTwist.length > 0) {
    twistItems.value = inspectTwist.map((item: any) => ({
      ...item,
      direction: item.direction || "",
      pitch: item.pitch || "",
      dia: item.dia || "",
      pitchRatio: item.pitchRatio || calculatePitchRatio(item.pitch, item.dia),
    }));
  }
  inspectionDialogVisible.value = true;
};
// 删除自检
const handleDeleteInspection = async (index: number) => {
  const item = inspectionList.value[index];
  if (!item || !item.id) {
    toast.error("删除失败:记录ID不存在");
    return;
  }
  uni.showModal({
    title: "提示",
    content: "确定要删除这条工艺记录吗?",
    success: async (res) => {
      if (res.confirm) {
        try {
          const { code } = await TwistApi.deleteStrandedWireInspectionStructureRecord(item.id);
          if (code === 200) {
            inspectionList.value.splice(index, 1);
            toast.success("删除成功");
          } else {
            toast.error("删除失败");
          }
        } catch (error) {
          console.error("删除工艺记录失败:", error);
          toast.error("删除失败");
        }
      }
    },
  });
};
// 保存自检
const handleSaveInspection = async () => {
  if (!inspectionFormRef.value) return;
  const result = await inspectionFormRef.value.validateAll();
  if (!result.valid) {
    toast.warning(result.message || "请完成必填项");
    return;
  }
  try {
    const submitData = {
      wireId: paramsId.value,
      strandedWireInspectionRecordId: formData.id,
      tensionSetting: formData.tensionSetting,
      recordPosition: inspectionForm.recordPosition,
      id: currentEditIndex.value >= 0 ? inspectionList.value[currentEditIndex.value].id : undefined,
      inspectionStructureResult: {
        twistedOuterDiameter: inspectionForm.twistedOuterDiameter,
        recordPosition: inspectionForm.recordPosition,
        inspectStructure: {
          structureFormula: inspectionForm.structureFormula,
          structureItems: structureItems.value.map((item: any) => ({
            structureName: item.structureName,
            structureValue: item.structureValue,
            actualValue1: item.actualValue1,
            actualValue2: item.actualValue2,
          })),
        },
        inspectTwist: twistItems.value.map((item: any) => ({
          twistName: item.twistName,
          direction: item.direction,
          pitch: item.pitch,
          dia: item.dia,
          pitchRatio: calculatePitchRatio(item.pitch, item.dia),
        })),
        productAppearance: inspectionForm.productAppearance,
        conclusion: inspectionForm.conclusion,
      },
    };
    const { code } = await TwistApi.saveStrandedWireInspectionStructureRecord(submitData);
    if (code === 200) {
      toast.success(currentEditIndex.value >= 0 ? "修改成功" : "添加成功");
      inspectionDialogVisible.value = false;
      await getInspectionList();
    } else {
      toast.error("保存失败");
    }
  } catch (error) {
    console.error("保存工艺记录失败:", error);
    toast.error("保存失败");
  }
};
onLoad(async (options: any) => {
  paramsId.value = options.id;
  await getData();
});
</script>
<style lang="scss" scoped>
.list {
  height: calc(100vh - 120px);
  padding: 12px;
  background: #f3f9f8;
  min-height: 100vh;
  padding-bottom: 80px;
}
  :deep() {
    .round {
      border-radius: 4px;
    }
.title {
  position: relative;
  margin-left: 10px;
  font-size: 16px;
  font-weight: 500;
  color: #0d867f;
}
.title::after {
  position: absolute;
  content: "";
  top: 4px;
  left: -10px;
  width: 4px;
  height: 16px;
  background: #0d867f;
  border-radius: 2px;
}
:deep() {
  .round {
    border-radius: 4px;
  }
}