yyb
5 天以前 491585f7ad453d889f71dc549f6a4d3dee74828f
src/pages/routingInspection/detail/indexJX.vue
@@ -73,11 +73,22 @@
        <wd-form-item label="张力设置" prop="twistTension">
          {{ formatValue(recordData.fixedInfo?.twistTension, "N/m") }}
        </wd-form-item>
        <wd-form-item label="绞制外径" prop="twistDiameter">
          {{ formatValue(recordData.inspectionResult?.twistDiameter, "mm") }}
        <!-- 绞制外径(可编辑) -->
        <wd-form-item label="绞制外径" prop="twistDiameter" required>
          <template v-if="isEdit">
            <wd-input
              v-model="formData.twistDiameter"
              placeholder="请输入绞制外径(mm)"
              type="number"
            />
          </template>
          <template v-else>
            {{ formatValue(formData.twistDiameter, "mm") }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 自检记录详情模块 -->
    <wd-row>
      <view style="margin: 10rpx">
@@ -97,27 +108,32 @@
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 结构检查模块 -->
    <wd-row>
      <view style="margin: 10rpx">
        <text class="title">{{ "结构检查" }}</text>
      </view>
      <wd-col :span="24">
        <wd-form-item label="成品结构" prop="inspectStructure">
          {{
            recordData.structureInfo.structureRecordResult.inspectStructure.structureFormula || "-"
          }}
        <wd-form-item label="成品结构" prop="structureFormula" required>
          <template v-if="isEdit">
            <wd-input v-model="formData.structureFormula" placeholder="请输入成品结构" />
          </template>
          <template v-else>
            {{ formData.structureFormula || "-" }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <wd-row v-if="recordData.structureInfo.structureRecordResult.inspectStructure.structureItems">
    <!-- 结构标准值和实测(可编辑) -->
    <wd-row v-if="formData.structureItems.length">
      <view style="margin: 10rpx">
        <text class="title">{{ "结构标准值和实测" }}</text>
      </view>
      <wd-col
        :span="24"
        v-for="(item, index) in recordData.structureInfo.structureRecordResult.inspectStructure
          .structureItems"
        v-for="(item, index) in formData.structureItems"
        :key="index"
        style="padding-bottom: 10px"
      >
@@ -125,26 +141,42 @@
          :label="formatValue(item.structureName)"
          label-width="400rpx"
          style="color: red"
          required
        ></wd-form-item>
        <wd-form-item label="标准值" prop="structureValue">
        <wd-form-item label="标准值" prop="structureValue" required>
          {{ formatValue(item.structureValue) }}
        </wd-form-item>
        <wd-form-item label="实测根数" prop="actualValue1">
          {{ formatValue(item.actualValue1, "根") }}
        <wd-form-item label="实测根数" prop="actualValue1" required>
          <template v-if="isEdit">
            <wd-input v-model="item.actualValue1" placeholder="请输入实测根数" type="number" />
          </template>
          <template v-else>
            {{ formatValue(item.actualValue1, "根") }}
          </template>
        </wd-form-item>
        <wd-form-item label="实测直径" prop="actualValue2">
          {{ formatValue(item.actualValue2, "mm") }}
        <wd-form-item label="实测直径" prop="actualValue2" required>
          <template v-if="isEdit">
            <wd-input
              v-model="item.actualValue2"
              placeholder="请输入实测直径(mm)"
              type="number"
            />
          </template>
          <template v-else>
            {{ formatValue(item.actualValue2, "mm") }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 绞线工艺质量控制模块 -->
    <wd-row v-if="recordData.structureInfo?.structureRecordResult?.inspectTwist">
    <!-- 绞线工艺质量控制(可编辑) -->
    <wd-row v-if="formData.inspectTwist.length">
      <view style="margin: 10rpx">
        <text class="title">{{ "绞线工艺质量控制" }}</text>
      </view>
      <wd-col
        :span="24"
        v-for="(item, index) in recordData.structureInfo.structureRecordResult.inspectTwist"
        v-for="(item, index) in formData.inspectTwist"
        :key="index"
        style="padding-bottom: 10px"
      >
@@ -152,57 +184,115 @@
          :label="formatValue(item.twistName)"
          label-width="400rpx"
          style="color: red"
          required
        ></wd-form-item>
        <wd-form-item label="绞向" prop="direction">
          {{ formatValue(item.direction) }}
        <wd-form-item label="绞向" prop="direction" required>
          <template v-if="isEdit">
            <wd-select-picker
              label=""
              v-model="item.direction"
              :columns="twistDirectionOptions"
              type="radio"
              placeholder="请选择绞向"
              :clearable="false"
            ></wd-select-picker>
          </template>
          <template v-else>
            {{ formatValue(item.direction) }}
          </template>
        </wd-form-item>
        <wd-form-item label="节距" prop="pitch">{{ formatValue(item.pitch, "mm") }}</wd-form-item>
        <wd-form-item label="节径比" prop="pitchRatio">
        <wd-form-item label="节距" prop="pitch" required>
          <template v-if="isEdit">
            <wd-input v-model="item.pitch" placeholder="请输入节距(mm)" type="number" />
          </template>
          <template v-else>
            {{ formatValue(item.pitch, "mm") }}
          </template>
        </wd-form-item>
        <wd-form-item label="节径比" prop="pitchRatio" required>
          {{ formatValue(item.pitchRatio) }}
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 外观和结论模块 -->
    <!-- 外观和结论(可编辑) -->
    <wd-row>
      <view style="margin: 10rpx">
        <text class="title">{{ "外观和结论" }}</text>
      </view>
      <wd-col :span="24">
        <wd-form-item label="结论" prop="conclusion">
          {{ formatValue(recordData.structureInfo.structureRecordResult.conclusion) }}
        <wd-form-item label="产品外观" prop="productAppearance" required>
          <template v-if="isEdit">
            <wd-checkbox-group
              v-model="formData.productAppearance"
              inline
              v-for="(opt, idx) in appearanceOptions"
              :key="idx"
              style="text-align: justify"
            >
              <wd-checkbox :modelValue="opt.value" style="width: 100px">
                {{ opt.label }}
              </wd-checkbox>
            </wd-checkbox-group>
          </template>
          <template v-else>
            {{ formatProductAppearance(formData.productAppearance) }}
          </template>
        </wd-form-item>
        <wd-form-item label="产品外观" prop="productAppearance">
          {{
            formatProductAppearance(
              recordData.structureInfo.structureRecordResult.productAppearance
            )
          }}
        <wd-form-item label="结论" prop="conclusion" required>
          <template v-if="isEdit">
            <wd-radio-group v-model="formData.conclusion" inline class="conclusion-radio-group">
              <wd-radio
                v-for="(opt, idx) in conclusionOptions"
                :key="idx"
                :value="opt.value"
                shape="dot"
              >
                {{ opt.label }}
              </wd-radio>
            </wd-radio-group>
          </template>
          <template v-else>
            {{ formatValue(formData.conclusion) }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 巡检结果模块 -->
    <wd-row>
      <view style="margin: 10rpx">
        <text class="title">{{ "巡检结果" }}</text>
      </view>
      <wd-col :span="24">
        <wd-form-item label="样品是否齐全" prop="sampleComplete">
          {{ formatValue(recordData.inspectionResult?.sampleComplete) }}
        <wd-form-item label="样品是否齐全" prop="sampleComplete" required>
          <template v-if="isEdit">
            <wd-radio-group v-model="formData.sampleComplete" inline class="conclusion-radio-group">
              <wd-radio
                v-for="(opt, idx) in sampleCompleteOptions"
                :key="idx"
                :value="opt.value"
                shape="dot"
              >
                {{ opt.label }}
              </wd-radio>
            </wd-radio-group>
          </template>
          <template v-else>
            {{ formatValue(formData.sampleComplete) }}
          </template>
        </wd-form-item>
      </wd-col>
    </wd-row>
    <!-- 附件模块 -->
    <!-- 附件模块(含上传功能) -->
    <wd-row class="attachment-section">
      <view style="margin: 10rpx">
        <text class="title">{{ "附件" }}</text>
      </view>
      <!-- 用 flex 容器包裹图片列,实现自动换行 -->
      <view class="attachment-grid">
        <wd-col
          v-for="(file, index) in recordData.structureInfo.files"
          :key="index"
          class="attachment-item"
        >
        <!-- 已上传附件(包含新上传的) -->
        <wd-col v-for="(file, index) in allFiles" :key="file.id || index" class="attachment-item">
          <wd-img :width="80" :height="80" :src="file.url" @click="previewImage(file.url)">
            <template #error>
              <view class="error-wrap">加载失败</view>
@@ -213,26 +303,276 @@
              </view>
            </template>
          </wd-img>
          <!-- 编辑模式下显示删除按钮 -->
          <!-- <wd-icon
            v-if="isEdit"
            name="close-circle"
            class="delete-icon"
            @click.stop="deleteFile(file.id || index)"
          ></wd-icon> -->
        </wd-col>
        <!-- 上传按钮(仅编辑模式显示) -->
        <wd-col v-if="isEdit" class="attachment-item upload-btn">
          <wd-upload
            :multiple="true"
            :max-count="5"
            :before-upload="beforeUpload"
            @success="handleUploadSuccess"
            @fail="handleUploadFail"
          >
            <view class="upload-icon">+</view>
          </wd-upload>
        </wd-col>
      </view>
    </wd-row>
    <wd-popup v-model="show" custom-style="border-radius:32rpx;" @close="handleClose">
      <div class="image-preview">
        <img :src="previewImageUrl" alt="预览图片" style="width: 100%; height: auto" />
      </div>
    </wd-popup>
    <Scan ref="scanRef" emitName="scan" />
    <wd-toast />
  </view>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
import Scan from "@/components/scan/index.vue";
import { useToast } from "wot-design-uni";
// 核心状态
const paramsId = ref("");
const recordData = ref<any>({});
const recordData = ref<any>({ structureInfo: { files: [], structureRecordResult: {} } });
const show = ref(false);
const previewImageUrl = ref("");
const isEdit = ref(false);
const tempFiles = ref<any[]>([]); // 临时存储新上传的附件
const deviceUid = ref("");
const scanRef = ref();
const toast = useToast();
// 表单临时数据(编辑模式绑定)
const formData = reactive({
  twistDiameter: "", // 绞制外径
  structureFormula: "", // 成品结构
  structureItems: [], // 结构标准值和实测
  inspectTwist: [], // 绞线工艺质量控制
  productAppearance: [] as string[], // 产品外观(改为数组存储选中值)
  conclusion: "", // 结论(改为数组存储选中值)
  sampleComplete: "", // 样品是否齐全
});
// 选项数据
const twistDirectionOptions = [
  { label: "左向", value: "左向" },
  { label: "右向", value: "右向" },
];
const appearanceOptions = [
  { label: "无外观问题", value: "无外观问题" },
  { label: "表面划伤", value: "表面划伤" },
  { label: "直径不均", value: "直径不均" },
  { label: "其他缺陷", value: "其他缺陷" },
];
const conclusionOptions = [
  { label: "合格", value: "合格" },
  { label: "不合格", value: "不合格" },
];
const sampleCompleteOptions = [
  { label: "是", value: "是" },
  { label: "否", value: "否" },
];
// 合并原有附件和新上传附件
const allFiles = computed(() => {
  return [...(recordData.value.structureInfo?.files || []), ...tempFiles.value];
});
// 初始化表单数据(接口数据同步到表单)
const initFormData = () => {
  const structureResult = recordData.value.structureInfo?.structureRecordResult || {};
  const inspectionResult = recordData.value.inspectionResult || {};
  // 基础可编辑字段
  formData.twistDiameter = inspectionResult.twistDiameter || "";
  formData.structureFormula = structureResult.inspectStructure?.structureFormula || "";
  formData.sampleComplete = inspectionResult.sampleComplete || "";
  formData.conclusion = structureResult.conclusion || "";
  // 修复产品外观和结论的数据格式
  formData.productAppearance = Array.isArray(structureResult.productAppearance)
    ? structureResult.productAppearance
    : structureResult.productAppearance
    ? [structureResult.productAppearance]
    : [];
  // 循环类字段(深拷贝避免原数据污染)
  formData.structureItems = JSON.parse(
    JSON.stringify(structureResult.inspectStructure?.structureItems || [])
  );
  formData.inspectTwist = JSON.parse(JSON.stringify(structureResult.inspectTwist || []));
  // 初始化绞向数据(确保有值)
  formData.inspectTwist.forEach((item: any) => {
    if (!item.direction) item.direction = "";
  });
};
// 获取详情数据
const getDetailData = async (id: string, deviceType: string) => {
  try {
    const response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({ id });
    recordData.value = response.data;
    tempFiles.value = []; // 清空临时文件
    initFormData(); // 数据返回后初始化表单
  } catch (error) {
    console.error("获取详情失败:", error);
    uni.showToast({ title: "加载失败", icon: "error" });
  }
};
// 页面加载
onLoad((options: any) => {
  paramsId.value = options.id;
  getDetailData(options.id, options.deviceType);
});
// 编辑模式切换
const editList = () => {
  isEdit.value = true;
};
// 取消编辑(重置表单)
const close = () => {
  isEdit.value = false;
  tempFiles.value = []; // 取消时清空临时上传的文件
  initFormData(); // 恢复原始数据
};
// 保存编辑(含必填项校验)
const saveList = async () => {
  // 1. 基础字段校验
  if (!formData.structureFormula) return uni.showToast({ title: "成品结构为必填项", icon: "none" });
  if (!formData.twistDiameter) return uni.showToast({ title: "绞制外径为必填项", icon: "none" });
  if (!formData.productAppearance.length)
    return uni.showToast({ title: "产品外观为必填项", icon: "none" });
  if (!formData.conclusion) return uni.showToast({ title: "结论为必填项", icon: "none" });
  if (!formData.sampleComplete)
    return uni.showToast({ title: "样品是否齐全为必填项", icon: "none" });
  // 2. 结构项循环校验
  for (const item of formData.structureItems) {
    if (!item.structureValue)
      return uni.showToast({ title: `${item.structureName}标准值为必填项`, icon: "none" });
    if (!item.actualValue1)
      return uni.showToast({ title: `${item.structureName}实测根数为必填项`, icon: "none" });
    if (!item.actualValue2)
      return uni.showToast({ title: `${item.structureName}实测直径为必填项`, icon: "none" });
  }
  // 3. 绞线工艺项循环校验
  for (const item of formData.inspectTwist) {
    if (!item.direction)
      return uni.showToast({ title: `${item.twistName}绞向为必填项`, icon: "none" });
    if (!item.pitch) return uni.showToast({ title: `${item.twistName}节距为必填项`, icon: "none" });
    if (!item.pitchRatio)
      return uni.showToast({ title: `${item.twistName}节径比为必填项`, icon: "none" });
  }
  console.log("1111", deviceUid.value);
  if (!deviceUid.value) return uni.showToast({ title: "请扫描二维码", icon: "none" });
  // 4. 提交数据到接口
  try {
    const res = await RoutingInspectionApi.strandedPatrolCheckInspection({
      deviceUid: deviceUid.value,
      id: paramsId.value,
      result: {
        twistDiameter: formData.twistDiameter,
        structureFormula: formData.structureFormula,
        structureItems: formData.structureItems,
        inspectTwist: formData.inspectTwist,
        productAppearance: formData.productAppearance,
        conclusion: formData.conclusion,
        sampleComplete: formData.sampleComplete,
      },
      inspectionResult: {
        sampleComplete: formData.sampleComplete,
      },
      processInspectionAttachmentList: tempFiles.value.map((f) => f.url), // 新上传的附件
    });
    if (res.code === 200) {
      uni.showToast({ title: "保存成功", icon: "success" });
      isEdit.value = false;
      getDetailData(paramsId.value, recordData.value.deviceType); // 刷新数据
    } else {
      uni.showModal({ title: res.msg || "保存失败", icon: "error" });
    }
  } catch (e) {
    console.error("保存失败:", e);
    uni.showModal({ title: e.message || "保存失败", icon: "error" });
  }
};
// 附件上传前置校验
const beforeUpload = (file: any) => {
  // 限制图片大小不超过2M
  const maxSize = 2 * 1024 * 1024;
  if (file.size > maxSize) {
    uni.showToast({ title: "图片大小不能超过2M", icon: "none" });
    return false;
  }
  return true;
};
// 附件上传成功回调
const handleUploadSuccess = (res: any) => {
  // 假设接口返回格式: { url: 'xxx', id: 'xxx' }
  if (Array.isArray(res)) {
    tempFiles.value = [
      ...tempFiles.value,
      ...res.map((file) => ({
        ...file,
        id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, // 生成临时ID
      })),
    ];
  } else {
    tempFiles.value.push({
      ...res,
      id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    });
  }
};
// 附件上传失败回调
const handleUploadFail = (err: any) => {
  uni.showToast({ title: "附件上传失败", icon: "error" });
};
// 删除附件
const deleteFile = (id: string | number) => {
  // 删除临时文件
  tempFiles.value = tempFiles.value.filter((file) => file.id !== id);
  // 如果是原有文件,需要标记删除(实际项目中可能需要接口交互)
  if (typeof id !== "string" || !id.startsWith("temp-")) {
    // 这里可以实现删除原有文件的逻辑
    recordData.value.structureInfo.files = recordData.value.structureInfo.files.filter(
      (file: any, index: number) => index !== id
    );
  }
};
// 图片预览
const previewImage = (url: string) => {
  previewImageUrl.value = url;
  show.value = true;
};
const handleClose = () => {
  show.value = false;
};
// 状态类型映射
const getStatusType = (status: number) => {
@@ -266,12 +606,6 @@
  }
};
// 获取外观文本
const getAppearanceText = (appearance: string[]) => {
  if (!appearance || appearance.length === 0) return "-";
  return appearance.join("、");
};
// 格式化产品外观显示
const formatProductAppearance = (productAppearance: string[]) => {
  if (!productAppearance || productAppearance.length === 0) return "-";
@@ -294,82 +628,40 @@
  });
};
// 格式化结构值显示
const formatStructureValue = (value1: any, value2: any) => {
  const val1 = value1 || "-";
  const val2 = value2 ? `${value2}mm` : "-";
  return { count: val1, diameter: val2 };
const openScan = () => {
  scanRef.value.triggerScan();
};
const getDetailData = async (id: string, deviceType: string) => {
const getScanCode = (params: any) => {
  console.log("完整参数:", params);
  let codeObj = {};
  try {
    let response;
    // 获取绞线单个结构
    response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({
      id: id,
    });
    recordData.value = response.data;
    console.log(recordData.value);
  } catch (error) {
    console.error("获取详情失败:", error);
    codeObj = JSON.parse(params.code);
  } catch (err) {
    console.error("JSON解析失败:", err);
    toast.error("扫码数据异常");
    return; // 解析失败直接返回,避免后续错误
  }
  deviceUid.value = codeObj?.uid;
  toast.success("扫码成功");
};
onLoad((options: any) => {
  paramsId.value = options.id;
  getDetailData(options.id, options.deviceType);
// 确保先移除再添加监听
const setupScanListener = () => {
  uni.$off("scan", getScanCode); // 先移除旧的
  uni.$on("scan", getScanCode); // 再添加新的
};
onUnmounted(() => {
  // 开启广播监听事件
  uni.$off("scan", getScanCode);
  console.log("离开1");
});
const previewImage = (url: string) => {
  previewImageUrl.value = url;
  show.value = true;
};
const handleClose = () => {
  show.value = false;
};
// 编辑列表
const editList = () => {};
// 关闭
const close = () => {};
// 保存列表
const saveList = async () => {
  // try {
  //   let response;
  //   // 保存列表
  //   response = await RoutingInspectionApi.saveStrandedInspectionStructureInfo({
  //     id: paramsId.value,
  //     structureInfo: recordData.value.structureInfo,
  //   });
  //   if (response.code === 200) {
  //     uni.showToast({
  //       title: "保存成功",
  //       icon: "success",
  //     });
  //     // 刷新详情数据
  //     getDetailData(paramsId.value, recordData.value.deviceType);
  //   } else {
  //     uni.showToast({
  //       title: response.msg || "保存失败",
  //       icon: "error",
  //     });
  //   }
  // } catch (error) {
  //   console.error("保存列表失败:", error);
  //   uni.showToast({
  //     title: "保存失败",
  //     icon: "error",
  //   });
  // }
};
onMounted(() => {
  // 开启广播监听事件
  setupScanListener();
  console.log("显示1");
});
</script>
<style lang="scss" scoped>
.placeholder {
  flex: 1;
}
.fixed-header {
  position: fixed;
  top: 44;
@@ -391,14 +683,8 @@
  gap: 10px;
}
.search-wrapper {
.placeholder {
  flex: 1;
  min-width: 0;
}
:deep(.search-wrapper .wd-search) {
  width: 100% !important;
  min-width: 0 !important;
}
.scan-wrapper {
@@ -413,11 +699,11 @@
.list {
  padding: 12px;
  padding-top: 84px;
  background: #f3f9f8;
  min-height: 100vh;
  box-sizing: border-box;
  overflow-y: auto;
}
.title {
@@ -439,6 +725,20 @@
  border-radius: 2px;
}
// 产品外观和结论选择器样式(一行两个)
.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
  padding: 8rpx 0;
}
.checkbox-item {
  width: calc(50% - 8rpx);
  margin-bottom: 8rpx;
}
// 附件相关样式
.attachment-section {
  width: 100%;
}
@@ -453,6 +753,39 @@
.attachment-item {
  width: calc(25% - 10px);
  box-sizing: border-box;
  position: relative;
}
.upload-btn {
  width: 80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed #ccc;
  border-radius: 4px;
  box-sizing: border-box;
}
.upload-icon {
  font-size: 32px;
  color: #0d867f;
}
// 附件删除图标
.delete-icon {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  background-color: rgba(255, 0, 0, 0.8);
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}
@media (max-width: 768px) {
@@ -460,4 +793,36 @@
    width: calc(25% - 10px);
  }
}
</style>
// 编辑模式下表单组件样式优化
:deep(.wd-form-item) {
  margin-bottom: 8rpx;
}
:deep(.wd-input, .wd-select, .wd-radio-group, .wd-checkbox-group) {
  width: 100%;
  box-sizing: border-box;
}
:deep(.wd-form-item__label) {
  &::after {
    content: "*";
    color: red;
    margin-left: 4rpx;
  }
}
// 修复选择器样式
:deep(.wd-select) {
  width: 100%;
}
:deep(.wd-checkbox) {
  margin-right: 0;
}
.conclusion-radio-group {
  display: flex;
  align-items: flex-start; // 垂直方向顶部对齐(上移关键)
  gap: 20rpx; // 选项之间的间距
}
</style>