spring
2025-11-20 5384750e59bbb27c54e090100429c48eaba46df0
src/pages/production/wire/selfInspect/form.vue
@@ -1,66 +1,333 @@
<template>
  <wd-form ref="form" :model="model" class="relative form_box">
    <wd-cell-group :border="true">
      <wd-input
        v-model="model.selfInspectName"
        label="自检名称"
        label-width="100px"
        prop="selfInspectName"
        clearable
        placeholder="请输入自检名称"
      />
      <wd-input
        v-model="model.unit"
        label="单位"
        label-width="100px"
        prop="unit"
        clearable
        placeholder="请输入单位"
      />
      <wd-input
        v-model="model.standard"
        label="标准值"
        label-width="100px"
        prop="standard"
        clearable
        placeholder="请输入标准值"
      />
      <wd-input
        v-model="model.selfInspectValue"
        label="自检值"
        label-width="100px"
        prop="selfInspectValue"
        clearable
        placeholder="请输入自检值"
      />
      <wd-input
        v-model="model.selfInspectResult"
        label="自检结果"
        label-width="100px"
        prop="selfInspectResult"
        clearable
        placeholder="请输入自检结果"
      />
    </wd-cell-group>
  </wd-form>
  <view class="form-container">
    <view class="dialog-header">
      <text class="dialog-title">{{ isEdit ? "编辑自检" : "新增自检" }}</text>
      <wd-icon name="close" class="close-icon" @click="handleClose"></wd-icon>
    </view>
    <view class="dialog-content">
      <wd-form ref="formRef" :model="formData">
        <!-- 基本信息 -->
        <view class="section-title">基本信息</view>
        <wd-cell-group border>
          <wd-input
            v-model="formData.fixedInfo.firstNo"
            label="首检单号"
            label-width="120px"
            placeholder="请输入首检单号"
          />
          <wd-input
            v-model="formData.fixedInfo.lastSlot"
            label="定径模具"
            label-width="120px"
            placeholder="请输入定径模具"
          />
        </wd-cell-group>
        <!-- 单丝直径 -->
        <view class="section-title">单丝直径(mm)</view>
        <wd-cell-group border>
          <wd-cell title="最大值" label-width="120px">
            <wd-input-number
              v-model="formData.inspectionResult.maxDia"
              :min="0"
              :precision="3"
              :step="0.01"
              placeholder="请输入最大值"
              :max="
                formData.inspectionResult.minDia !== null &&
                formData.inspectionResult.minDia !== undefined
                  ? undefined
                  : 999999
              "
            />
          </wd-cell>
          <wd-cell title="最小值" label-width="120px">
            <wd-input-number
              v-model="formData.inspectionResult.minDia"
              :min="0"
              :precision="3"
              :step="0.01"
              placeholder="请输入最小值"
              :max="
                formData.inspectionResult.maxDia !== null &&
                formData.inspectionResult.maxDia !== undefined
                  ? formData.inspectionResult.maxDia
                  : 999999
              "
            />
          </wd-cell>
        </wd-cell-group>
        <!-- 外观 -->
        <view class="section-title">外观</view>
        <wd-cell-group border>
          <wd-cell title="外观质量" label-width="120px">
            <view class="checkbox-group">
              <wd-checkbox
                v-for="option in appearanceOptions"
                :key="option.value"
                :modelValue="
                  Array.isArray(formData.inspectionResult.appearance)
                    ? formData.inspectionResult.appearance.includes(String(option.value))
                    : false
                "
                shape="square"
                @change="(val) => handleAppearanceChange(String(option.value), val)"
              >
                {{ option.label }}
              </wd-checkbox>
            </view>
          </wd-cell>
        </wd-cell-group>
        <!-- 成盘质量 -->
        <view class="section-title">成盘质量</view>
        <wd-cell-group border>
          <wd-cell title="卷绕紧密" label-width="120px">
            <wd-radio-group v-model="formData.inspectionResult.windingTightness" size="small">
              <wd-radio value="是">是</wd-radio>
              <wd-radio value="否">否</wd-radio>
            </wd-radio-group>
          </wd-cell>
          <wd-cell title="排列整齐" label-width="120px">
            <wd-radio-group v-model="formData.inspectionResult.arrangementNeatness" size="small">
              <wd-radio value="是">是</wd-radio>
              <wd-radio value="否">否</wd-radio>
            </wd-radio-group>
          </wd-cell>
          <wd-cell title="外层铝线离侧板边缘距离(mm)" label-width="200px">
            <wd-input-number
              v-model="formData.inspectionResult.aluminumWireDistance"
              :min="0"
              :precision="0"
              placeholder="请输入距离"
              :class="{ 'text-danger': formData.inspectionResult.aluminumWireDistance < 25 }"
            />
          </wd-cell>
        </wd-cell-group>
        <!-- 其他信息 -->
        <view class="section-title">其他信息</view>
        <wd-cell-group border>
          <wd-cell title="成品模后接头情况" label-width="120px">
            <wd-radio-group v-model="formData.inspectionResult.jointCondition" size="small">
              <wd-radio value="有">有</wd-radio>
              <wd-radio value="无">无</wd-radio>
            </wd-radio-group>
          </wd-cell>
          <wd-cell title="结论" label-width="120px">
            <wd-radio-group v-model="formData.inspectionResult.conclusion" size="small">
              <wd-radio value="合格">合格</wd-radio>
              <wd-radio value="不合格">不合格</wd-radio>
            </wd-radio-group>
          </wd-cell>
        </wd-cell-group>
      </wd-form>
    </view>
    <view class="dialog-footer">
      <wd-button plain @click="handleClose" style="margin-right: 10px">取消</wd-button>
      <wd-button type="primary" class="ml-2" @click="handleSubmit">保存</wd-button>
    </view>
  </view>
</template>
<script setup lang="ts">
import useFormData from "@/hooks/useFormData";
const { form: model } = useFormData({
  selfInspectName: undefined, // 自检名称
  unit: undefined, // 单位
  standard: undefined, // 标准值
  selfInspectValue: undefined, // 自检值
  selfInspectResult: undefined, // 自检值
});
import { ref, watch, computed } from "vue";
import { dayjs } from "wot-design-uni";
const props = defineProps<{
  visible: boolean;
  formData: any;
  appearanceOptions: Array<{ label: string; value: string | number }>;
  previousAppearanceValue?: string[];
}>();
const emit = defineEmits<{
  (e: "update:visible", value: boolean): void;
  (e: "submit", data: any): void;
  (e: "close"): void;
}>();
const formRef = ref();
const isEdit = computed(() => !!props.formData?.id && !props.formData?.isNew);
// 存储前一个外观质量值
const previousAppearanceValue = ref<string[]>(props.previousAppearanceValue || []);
// 处理外观质量互斥逻辑
const handleAppearanceQualityChange = (
  selectedValues: string[],
  previousValues: string[],
  allOptions: Array<{ label: string; value: string | number }>
): string[] => {
  if (!allOptions || allOptions.length === 0) {
    return selectedValues;
  }
  const noIssueOption = allOptions.find(
    (item) => item.label === "无外观问题" || item.value === "无外观问题"
  );
  if (!noIssueOption) {
    return selectedValues;
  }
  const noIssueValue = String(noIssueOption.value);
  const hasNoIssue = selectedValues.includes(noIssueValue);
  const hadNoIssue = previousValues.includes(noIssueValue);
  const isNewlySelectedNoIssue = !hadNoIssue && hasNoIssue;
  const isSelectingOtherWithNoIssue =
    hadNoIssue && hasNoIssue && selectedValues.length > previousValues.length;
  let result: string[];
  if (isNewlySelectedNoIssue) {
    result = [noIssueValue];
  } else if (isSelectingOtherWithNoIssue) {
    result = selectedValues.filter((val) => val !== noIssueValue);
  } else {
    result = selectedValues;
  }
  return result;
};
// 处理外观选择变化
const handleAppearanceChange = (optionValue: string, checked: boolean) => {
  const currentValues = Array.isArray(props.formData.inspectionResult.appearance)
    ? props.formData.inspectionResult.appearance
    : [];
  let newValues: string[];
  if (checked) {
    newValues = [...currentValues, optionValue];
  } else {
    newValues = currentValues.filter((v: string) => v !== optionValue);
  }
  const processedValues = handleAppearanceQualityChange(
    newValues,
    previousAppearanceValue.value,
    props.appearanceOptions
  );
  props.formData.inspectionResult.appearance = JSON.parse(JSON.stringify(processedValues));
  previousAppearanceValue.value = JSON.parse(JSON.stringify(processedValues));
};
const handleClose = () => {
  emit("update:visible", false);
  emit("close");
};
const handleSubmit = () => {
  // 验证单丝直径:最大值应该大于或等于最小值
  const maxDia = props.formData.inspectionResult.maxDia;
  const minDia = props.formData.inspectionResult.minDia;
  if (maxDia !== null && minDia !== null && maxDia < minDia) {
    uni.showToast({
      title: "单丝直径最大值不能小于最小值",
      icon: "none",
    });
    return;
  }
  // 验证外层铝线离侧板边缘距离
  const aluminumWireDistance = props.formData.inspectionResult.aluminumWireDistance;
  if (aluminumWireDistance < 25) {
    uni.showToast({
      title: "外层铝线离侧板边缘距离不能低于25mm",
      icon: "none",
    });
    return;
  }
  emit("submit", props.formData);
};
// 监听 visible 变化,初始化 previousAppearanceValue
watch(
  () => props.visible,
  (newVal) => {
    if (newVal && props.formData?.inspectionResult?.appearance) {
      previousAppearanceValue.value = JSON.parse(
        JSON.stringify(props.formData.inspectionResult.appearance || [])
      );
    }
  }
);
</script>
<style lang="scss" scoped>
.form_box {
.form-container {
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
.submit_btn {
  position: absolute;
  bottom: 0;
  width: 100%;
.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #e6e6e6;
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 10;
}
.dialog-title {
  font-size: 16px;
  color: #333;
  font-weight: 500;
}
.close-icon {
  font-size: 20px;
  color: #999;
  padding: 4px;
}
.dialog-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.section-title {
  font-size: 14px;
  font-weight: 700;
  color: #252525;
  margin: 16px 0 8px 0;
  padding-bottom: 8px;
  border-bottom: 1px solid #e6e6e6;
}
.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
:deep(.wd-checkbox) {
  margin-right: 0;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding: 16px;
  border-top: 1px solid #e6e6e6;
  gap: 8px;
}
.text-danger {
  :deep(.wd-input-number__input) {
    color: #f56c6c;
    border-color: #f56c6c;
  }
}
</style>